mongodb 增删改查
mongdb 是一个面向文档的数据库,不是关系型数据库
不采用关系型主要是为了获得更好的扩展性,与关系数据库相比,面向文档的数据库不再有 行的概念 取而代之的是更灵活的文档
在文档中嵌入文档和数组 能够使用一条记录表现复杂的层级关系 与现代的面向对象开发者对数据的看法一致
没有预定义模式,文档的键值不在是固定的类型大小,没有固定的模式,根据需要添加或删除字段变得更容易了。通常由于开发者能够进行快速迭代,所以开发进程得以加快。而且,实验更容易进行。开发者能尝试大量的数据模型,从中选一个最好的
易扩展
随着可用带宽的增长和存储器价格的下降,小规模的引弓程序需要的存储量也很大,甚至超出数据库处理能力,T级数据司空见惯
由于需要存储的数据量不断增长,开发者面临一个问题:应该如何扩展数据库,分为纵向扩展和横向扩展,纵向扩展是最省力的做法,但缺点是大型机一般都非常贵,而且
当数据量达到机器的物理极限时,花再多的钱也买不到更强的机器了,此时选择横向扩展更为合适,但横向扩展带来的另外一个问题就是需要管理的机器太多。
MongoDB的设计采用横向扩展。面向文档的数据模型使它能很容易地在多台服务器之间进行数据分割。MongoDB能够自动处理跨集群的数据和负载,自动重新分配文档,以及将
用户的请求路由到正确的机器上。这样,开发者能够集中精力编写应用程序,而不需要考虑如何扩展的问题。如果一个集群需要更大的容量,只需要向集群添加新服务器,MongoDB就会自动将现有的数据向新服务器传送
### 功能全
MongoDB作为一款通用型数据库,除了能够创建、读取、更新和删除数据之外,还提供了一系列不断扩展的独特功能
1、索引
支持通用二级索引,允许多种快速查询,且提供唯一索引、复合索引、地理空间索引、全文索引
2、聚合
支持聚合管道,用户能通过简单的片段创建复杂的集合,并通过数据库自动优化
3、特殊的集合类型
支持存在时间有限的集合,适用于那些将在某个时刻过期的数据,如会话session。类似地,MongoDB也支持固定大小的集合,用于保存近期数据,如日志
4、文件存储
支持一种非常易用的协议,用于存储大文件和文件元数据。MongoDB并不具备一些在关系型数据库中很普遍的功能,如链接join和复杂的多行事务。省略
这些的功能是处于架构上的考虑,或者说为了得到更好的扩展性,因为在分布式系统中这两个功能难以高效地实现
### 卓越的性能
MongoDB的一个主要目标是提供卓越的性能,这很大程度上决定了MongoDB的设计。MongoDB把尽可能多的内存用作缓存cache,视图为每次查询自动选择正确的索引。
总之各方面的设计都旨在保持它的高性能
虽然MongoDB非常强大并试图保留关系型数据库的很多特性,但它并不追求具备关系型数据库的所有功能。只要有可能,数据库服务器就会将处理逻辑交给客户端。这种精简方式的设计是MongoDB能够实现如此高性能的原因之一
文档中的键/值对是有序的。
#2、文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
#3、MongoDB区分类型和大小写。
#4、MongoDB的文档不能有重复的键。
#5、文档中的值可以是多种不同的数据类型,也可以是一个完整的内嵌文档。文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。
文档键命名规范:
#1、键不能含有\0 (空字符)。这个字符用来表示键的结尾。
#2、.和$有特别的意义,只有在特定环境下才能使用。
#3、以下划线"_"开头的键是保留的(不是严格要求的)。
下载安装
4.0下载地址:
https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-4.0.8-signed.msi
安装时去除多余的组件安装提高速度:
![2018081215270025](https://ws2.sinaimg.cn/large/006tNc79ly1g22v4jcxoyj30dv0asq3e.jpg)
![2018081215270126](https://ws1.sinaimg.cn/large/006tNc79ly1g22v45enftj30dv0as74y.jpg)
![2018081215270328](https://ws3.sinaimg.cn/large/006tNc79ly1g22v49gf16j30dv0as74p.jpg)
此时MongoDB已经开启,浏览器访问<http://localhost:27017/>,页面上输出:
It looks like you are trying to access MongoDB over HTTP on the native driver port.
说明MongoDB已经启动了,且它的默认端口(27017)没有被占用。
## 开始使用:
运行bin下的终端程序mongo.exe 其与mysql性质相同都是客户端!
'mongo' 看见欢迎信息则说明登录成功
![屏幕快照 2019-04-15 上午5.24.02](https://ws1.sinaimg.cn/large/006tNc79ly1g22v7rhx8sj30pt0c0gmo.jpg)
此时没有任何的权限限制,默认是管理员角色
默认情况下mongodb不会加载认证信息就像mysql跳过授权表一样,创建完账号用户需要开启用户认证:
##### 具体方法:
修改配置文档mongod.cfg(位置:安装目录\bin 下)
首先,将bind_ip改为0.0.0.0 (让其他电脑可以访问,用于远程连接,如果bind_ip是127.0.0.1的话,就只能本地访问)
```mysql
security:
authorization: enabled
# 注意缩进
```
然后找到 #security:改成下图所示,开启安全认证。
![20180725182019556](https://ws3.sinaimg.cn/large/006tNc79ly1g22w8uzytdj30e40ll75n.jpg)
重启MongoDB Server服务,启用认证!
#### 账号测试:
```mysql
#直接mongo进入程序 已经无法查看数据库
show dbs
#登录方式1: authenticationDatabase指定数据库
mongo --port 27017 -u "root" -p "123" --authenticationDatabase "admin"
#登录方式2:进入mongo后
use admin
db.auth("root","123")
#删除账号
db.dropUser('用户名');
#修改密码
db.changeUserPassword(用户名, 新密码);
1、在概念上,MongoDB的文档与Javascript的对象相近,因而可以认为它类似于JSON。JSON(http://www.json.org)是一种简单的数据表示方式:其规范仅用一段文字就能描述清楚(其官网证明了这点),且仅包含六种数据类型。
2、这样有很多好处:易于理解、易于解析、易于记忆。然而从另一方面说,因为只有null、布尔、数字、字符串、数字和对象这几种数据类型,所以JSON的表达能力有一定的局限。
3、虽然JSON具备的这些类型已经具有很强的表现力,但绝大数应用(尤其是在于数据库打交道时)都还需要其他一些重要的类型。例如,JSON没有日期类型,这使得原本容易日期处理变得烦人。另外,JSON只有一种数字类型,无法区分浮点数和整数,更别区分32位和64位了。再者JSON无法表示其他一些通用类型,如正则表达式或函数。
4、MongoDB在保留了JSON基本键/值对特性的基础上,添加了其他一些数据类型。在不同的编程语言下,这些类型的确切表示有些许差异。下面说明了MongoDB支持的其他通用类型,以及如何正在文档中使用它们
```python
#1、null:用于表示空或不存在的字段
d={'x':null}
#2、布尔型:true和false
d={'x':true,'y':false}
#3、数值
d={'x':3,'y':3.1415926}
#4、字符串
d={'x':'egon'}
#5、日期
d={'x':new Date()}
d.x.getHours()
#6、正则表达式
d={'pattern':/^egon.*?nb$/i}
正则写在//内,后面的i代表:
i 忽略大小写
m 多行匹配模式
x 忽略非转义的空白字符
s 单行匹配模式
#7、数组
d={'x':[1,'a','v']}
#8、内嵌文档
user={'name':'jerry','addr':{'country':'China','city':'YT'}}
user.addr.country
#9、对象id:是一个12字节的ID,是文档的唯一标识,不可变
d={'x':ObjectId()}
#案例:
db.tb.insert({"a":null,"b":1.1,"c":true,"d":100,"e":"aaaaaa","f":new Date(),"g":/^jerry.*nice$/i,"h":[1,2],"j":{"name":"smallJerry"}})
db.tb.find()
db.tb.find().pretty() # 格式化显示
```
## _id和ObjectId
```python
"""
MongoDB中存储的文档必须有一个"_id"键。这个键的值可以是任意类型,默认是个ObjectId对象。
在一个集合里,每个文档都有唯一的“_id”,确保集合里每个文档都能被唯一标识。
不同集合"_id"的值可以重复,但同一集合内"_id"的值必须唯一
#1、ObjectId
ObjectId是"_id"的默认类型。因为设计MongoDb的初衷就是用作分布式数据库,所以能够在分片环境中生成
唯一的标识符非常重要,而常规的做法:在多个服务器上同步自动增加主键既费时又费力,这就是MongoDB采用
ObjectId的原因。
ObjectId采用12字节的存储空间,是一个由24个十六进制数字组成的字符串
0|1|2|3| 4|5|6| 7|8 9|10|11
时间戳 机器 PID 计数器
如果快速创建多个ObjectId,会发现每次只有最后几位有变化。另外,中间的几位数字也会变化(要是在创建过程中停顿几秒)。
这是ObjectId的创建方式导致的,如上图
时间戳单位为秒,与随后5个字节组合起来,提供了秒级的唯一性。这个4个字节隐藏了文档的创建时间,绝大多数驱动程序都会提供
一个方法,用于从ObjectId中获取这些信息。
因为使用的是当前时间,很多用户担心要对服务器进行时钟同步。其实没必要,因为时间戳的实际值并不重要,只要它总是不停增加就好。
接下来3个字节是所在主机的唯一标识符。通常是机器主机名的散列值。这样就可以保证不同主机生成不同的ObjectId,不产生冲突
接下来2个字节确保了在同一台机器上并发的多个进程产生的ObjectId是唯一的
前9个字节确保了同一秒钟不同机器不同进程产生的ObjectId是唯一的。最后3个字节是一个自动增加的 计数器。确保相同进程的同一秒产生的
ObjectId也是不一样的。
#2、自动生成_id
如果插入文档时没有"_id"键,系统会自帮你创建 一个。可以由MongoDb服务器来做这件事。
但通常会在客户端由驱动程序完成。这一做法非常好地体现了MongoDb的哲学:能交给客户端驱动程序来做的事情就不要交给服务器来做。
这种理念背后的原因是:即便是像MongoDB这样扩展性非常好的数据库,扩展应用层也要比扩展数据库层容易的多。将工作交给客户端做就
减轻了数据库扩展的负担。
查看数据库
show dbs
创建数据库
use 数据库名称
#如果有则切换没有则创建新的,注意的是如果如果库中没有数据show dbs 中则不显示
db.dropDatabase()
#创建集合:
db.user
#查看集合:
show collections
show tables
# 同样的数据集合中没有数据则 不会显示
# 一下数据库之间没有任何关系仅仅是名字有相同部分 数据之间的关系需要应用程序维护
db.blog
db.blog.user
db.blog.common
#删除集合:
db.blog.user.drop()
新建用户
db.createUser({"user":"root","pwd":"123",roles:[{"role":"root","db":"admin"}]})
db.createUser(
{
user: "jerry",
pwd: "123",
roles: [ { role: "readWrite", db: "test" },
{ role: "read", db: "db1" } ]
}
)
```mysql
#直接mongo进入程序 已经无法查看数据库
show dbs
#登录方式1: authenticationDatabase指定数据库
mongo --port 27017 -u "root" -p "123" --authenticationDatabase "admin"
#登录方式2:进入mongo后
use admin
db.auth("root","123")
#删除账号
db.dropUser('用户名');
#修改密码
db.changeUserPassword(用户名, 新密码);
```
新增记录
db.user.insert({"_id":1,"name":"lf"})
db.user.insertMany({"_id":1,"name":"lf"},{"_id":3,"name":"lxm"})
查询:
单条件 =
> < != >= <=
gt lt ne gte lte //中间写正则
db.user.find({"name":"lxm"})
db.user.find({"name";/^L/})
逻辑运算符
and or not
db.user.find({"name":/^l.*$/},{"name":/m$/}) and
db.user.find({"$or":[{"name":/^l/},{"_id":{"$gte":2}}]}) or
db.user.find({"_id":{"$mod":[2,1]}})
db.user.find({'_id':{"$not":{"$mod":[2,1]}}})
db.user.find({
"_id":{"$in":[1,2]}
})
# id 不在 [1,2]内的
db.user.find({
"_id":{"$nin":[1,2]}
})
指定字段
db.user.find({'_id':3},{'_id':0,'name':1,'age':1})
1表示展示 0不展示
_id默认为1 其他默认为0
# 查看所有人的 第一个和第二个爱好
db.student.find({},{"hobbies":{"$slice":[0,1]}})
# $slice [1,1] 表示的是从第1个开始取1个
db.student.find({},{"hobbies":{"$slice":[1,1]}})
=============================查询数组=============================
#1、查看有dancing爱好的人
db.user.find({'hobbies':'dancing'})
#2、查看既有dancing爱好又有tea爱好的人
db.user.find({
'hobbies':{
"$all":['dancing','tea']
}
})
#3、查看第4个爱好为tea的人
db.user.find({"hobbies.3":'tea'})
#4、查看所有人最后两个爱好
db.user.find({},{'hobbies':{"$slice":-2},"age":0,"_id":0,"name":0,"addr":0})
#5、查看所有人的第2个到第3个爱好
db.user.find({},{'hobbies':{"$slice":[1,2]},"age":0,"_id":0,"name":0,"addr":0})
`python
#1、删除多个中的第一个
db.user.deleteOne({ 'age': 8 })
#2、删除国家为China的全部
db.user.deleteMany( {'addr.country': 'China'} )
#3、删除全部
db.user.deleteMany({})