MongoDB
文章目录
- MongoDB
- 一、基本介绍
- 二、增删改查操作
- 2.1 创建文档
- 2.2 读取文档
- 2.2.1 读取全部文档
- 2.2.2 匹配查询
- 2.2.3 比较操作符
- 2.2.4 逻辑操作符
- 2.2.5 字段操作符
- 2.2.6 数组操作符
- 2.3 文档游标
- 2.4 更新文档
- 2.5 删除文档
- 2.6 删除集合
一、基本介绍
概念
MongoDB是存储JSON文档的非关系型数据库,结构如下图:
一个数据库中有很多集合,一个集合中有很多文档。
运行
使用Docker运行MongoDB:
docker run --name mymongo -v /mymongo/data:/data/db -d mongo
# --name给容器起别名
MongoDB默认使用27017端口
查看日志
docker logs 容器名称
Mongo Shell
Mongo Shell 是用来操作MongoDB的JS客户端
# 运行Mongo Shell
docker exec -it 容器名称 mongo
二、增删改查操作
存储在MongoDB的每篇文档都有一个专属的id,称为文档主键,存储在 _id
字段中:
- 主键具有唯一性(不同文档的主键不能重复),支持除数组之外的所有数据类型,一篇文档可以作为另一篇文档的主键,称为复合主键。
- 如果创建文档时没有指定主键,则会默认创建一个对象主键
ObjectId("包含创建时间的字串")
。
- 提取对象主键的创建时间:
ObjectId("xxx").getTimestamp()
2.1 创建文档
- 使用
db.集合.insert()
或者db.集合.save()
命令
- insert命令又分为insertOne、insertMany、insert
基本语法:
db.<collection>.insertOne(
<document>,
{
writeConcern: <document>
}
)
-
<collection>
要替换成文档存放的集合,此集合如果不存在则自动创建 -
<document>
要替换成写入的文档本身 writeConcern: <document>
定义了本次文档创建操作的安全写级别
- 安全写级别用来判断一次数据库写入操作是否成功
- 安全写级别越高,丢失数据的风险就越低,然而写入操作的延迟也就越高
- 如果不指定安全写级别,则MongoDB会使用默认的级别
- 注意:安全写级别和文档的 JSON 键值对不在一个大括号中,需要另写一个大括号
演示:
运行Mongo Shell
docker exec -it 容器名称 mongo
使用test数据库
use test
# 数据库存在则切换到该数据库,数据库不存在则自动创建该数据库并切换到该数据库
查看test数据库的所有集合
show collections
# 现在新创建的test数据库中还没有集合
将文档写入accounts集合
db.accounts.insertOne(
{
_id: "account1",
name: "alice",
balance: 100
}
)
指定了主键,但没有指定安全写级别
运行结果
{ "acknowledged" : true, "insertedId" : "account1" }
-
"acknowledged" : true
表示安全写级别被启用,此时显示的是默认的安全写级别的状态 -
"insertedId" : "account1"
显示了被写入文档的主键
如果insertOne遇到了错误
使用重复的主键id创建一个新文档:
出现了错误:
可以捕获异常:
库函数print打印出的异常消息更加直观:
自动生成主键id
省略 _id
字段即可:
创建多个文档
基本语法:
- ordered 参数用来决定是否要按顺序写入这些文档,取值为true或false,默认取值为true
- 如果 ordered 的取值为false,则MongoDB可以打乱文档顺序写入,加快写入速度
示例:
如果insertMany遇到了错误
- 顺序写入时,一旦遇到了错误,剩余的文档无论正确与否,都不会被执行
- 乱序写入时,即使某些文档造成了错误,但剩余的正确文档仍然会被写入
创建多个或单个文档
基本语法:
示例:
save命令
基本语法:
- save指令处理一个新文档时,会调用insert指令
复合主键
- 复合主键也要满足唯一性,否则报错
- 复合主键中的内容相同但是键值对的顺序不同不认为主键重复
2.2 读取文档
基本语法:
db.集合.find(<query>, <projection>)
-
query
表示 JSON 格式的查询条件(可选),为空则表示没有查询条件,即查询全部文档 projection
表示对结果进行投影操作(可选)
- 可以返回文档的部分字段,提高效率(注意不是返回部分文档)
- 如果省略投影字段,则返回所有符合条件的完整字段的文档
- 无论是否使用投影,查询结果的个数都是一样的,只不过使用了投影会使得返回的文档不显示全部字段
2.2.1 读取全部文档
db.集合.find()
更直观的显示文档:db.集合.find().pretty()
2.2.2 匹配查询
2.2.3 比较操作符
注意:本来查询条件是key-value共用一个大括号,现在是比较符和value还要另占一个大括号。
示例1:
注意:$ne
会查询出不包含查询字段的文档,可以理解为不包含自然就不等于。
示例2:
比较运算符也可以按照字典顺序比较:
示例3:
注意:
- in、nin 操作符对应的value值要放在一个数组中
- nin 会筛选出不包含查询字段的文档
示例4:
in结合正则表达式使用:
2.2.4 逻辑操作符
注意:使用逻辑操作符还需要再加一层大括号。
示例1:
注意:not 也会筛选出不包含查询字段的文档。
示例2:
简化写法1(用在不同字段上):
简化写法2(用在同一字段上):
示例3:
注意:nor 会筛选出不包含查询字段的文档。
2.2.5 字段操作符
$exists
:匹配是否存在指定字段的文档
$type
:匹配字段类型符合查询值的文档
示例1:
示例2:
原本会得到不包含查询字段的文档,加上这个条件后不包含查询字段的文档就不会被查询到:
示例3:
示例4:
2.2.6 数组操作符
all示例:
elemMatch示例:
2.3 文档游标
执行 db.集合.find()
返回的是一个文档集合的游标:var myCursor = db.集合.find()
,在不迭代游标的情况下,只列出前20个文档。
可以使用游标下标直接访问文档集合中的某一个文档:
遍历完游标中所有的文档之后,或者在10分钟之后,游标便自动关闭。
游标函数:
- hasNext & next
- forEach
- limit & skip
注意:limit(0)
表示返回所有结果。
- count
基本语法:cursor.count(<boolean>)
,括号中为空则默认是false。
当括号中为 false 时,limit 和 skip 二者无效;当括号中为 true 时,才会使用 limit 和 skip 的效果: - sort
1表示从小到大的正向排序,-1表示从大到小的逆向排序: - 两个注意点
- skip 在 limit 之前执行
- sort 在 skip 和 limit 之前执行
文档投影:
使用文档投影可以只返回文档的部分字段:1表示返回,0表示不返回:
注意:除了文档主键之外,不可以同时使用包含和不包含两种投影操作:
2.4 更新文档
基本语法:
db.集合.update(<query>, <update>, <options>)
- query 定义了被更新文档的筛选条件,与 find 中的筛选条件作用一致
- update 定义了更新结果
- options 定义了一些更新操作的参数
注意:以上三者都是可选的。
示例:
如果可选的 <update> 中不包含任何更新操作符,更新命令将会使用 <update> 文档直接替换集合中对应的整篇文档(全部字段):
注意:
- 主键字段是不可以更改的,如果一定要使用主键字段,<update> 中的主键字段值务必与原内容一致。
- 如果有多篇文档可以匹配到 <query>,使用不包含更新操作符的 <update> 更新整篇文档时只会更新第一篇。
更新操作符:
如果可选的 <update> 中包含更新操作符,更新命令将会使用 <update> 文档替换集合中对应文档的特定字段:
$set:
更新或新增字段:
更新数组中的字段:
注意:如果插入时超过了数组的范围,导致数组中有空位,则空位默认填充null。
$unset:
删除字段:
注意:如果删除的是数组元素,则不会改变数组长度,只会将对应元素置为null。
$rename:
重命名文档:
- 如果重命名不存在的文档,则不会改变原文档内容
- 如果新的字段名已经存在,则会置空(unset)原文档同名的字段,并将所要修改的字段重命名
- 内嵌文档重命名:
注意:对于内嵌数组,此方式无法使用,会报错。
$inc & $mul:
注意:
- 这两个命令只能作用在数字字段上
- 当作用在不存在的字段时,
$inc
会创建字段,并将字段值设置为指定的增减值;$mul
会创建字段,但是字段值为0
$min & $max:
比较原文档值与新值之后更新值:
注意:如果被更新的字段不存在,这两个命令会创建字段,字段值为更新值。
数组更新操作符:
这些操作符只能作用在数组字段上:
$addToSet:
注意:
- 如果要插入的值已经存在于数组字段中,此命令不会再插入重复值
- 此命令插入文档或数组时,内容相同顺序不同不认为重复
- 一次添加多个值:
$pop:
删除数组字段的第一个元素或者最后一个元素,1表示删除最后一个元素,-1表示删除第一个元素:
注意:删除数组中最后一个元素后,数组会置空。
$pull & $pullAll:
从数组字段中删除特定元素:
$push:
向数组字段中添加元素:
2.5 删除文档
基本语法:
db.集合.remove(<query>, <options>)
- query:查询条件
- 筛选条件为空表示删除所有文档
- options:删除操作的参数
默认情况下,remove
命令会删除所有符合筛选条件的文档,如果只想删除满足筛选条件的第一篇文档,可以使用 justOne
参数:
2.6 删除集合
remove
命令可以删除集合内的所有文档,但是不会删除集合,删除集合的方式如下: