Document文档
在MongoDB中文档是指多个键及其关联的值有序地放置在一起就是文档,其实指的就是数据。
MongoDB中的文档地数据结构和JSON基本一样,所有存储在集合中地数据都是BSON。
新增文档
insert
此方法是插入文档最常用的方法,可以插入单条或多条文档。
语法格式:
db.collection.insert(
<document or documents>,
{
writeConcern:<document>,
ordered:<boolean>
}
)
参数说明:
document or documents:一条文档或多条文档
- 一条:{doc}
- 多条:[{doc1},{doc2}...]
writeConcern:可选参数,表示是否使用写入策略,该策略较为复杂,这里暂不讨论
ordered:是否为有序插入,默认为true
- true:文档中有一个发生错误,mongodb将不再继续插入后续文档
- false:当文档有一个发生错误,不会影响后续文档地插入
db.user.insert(
[{ ‘name‘:‘wj‘,‘age‘:23},{‘name‘:‘zhangsan‘,‘age‘:20}]
)
save
save也可以插入一条或多条文档,但是insert方法插入主键相同的文档时会报错,而使用save方法插入主键相同的文档时则会覆盖原文档。
db.collection.save(
<document or documents >,
{
writeConcern:<document>
}
)
insertOne
insertOne只能插入一条文档,如果使用该方法插入多条文档,则mongodb只会新增第一条文档。
db.collection.insertOne(
<document>,
{
writeConcern:<document>
}
)
insertMany
该方法可以插入多个文档,语法与insert方法一样,插入成功后,会返回插入文档的主键。
注意,使用insertMany插入单条文档,也必须用中括号括起来,否则报错。
变量定义和使用
test_user=({ ‘name‘:‘wj‘,‘age‘:23})
db.user.insert(test_user)
test_user2=([{ ‘name‘:‘wj‘,‘age‘:23},{ ‘name‘:‘wj2‘,‘age‘:24}])
db.user.insertMany(test_user2)
查询文档
find
语法格式:
db.collection.find(<query>,<projection>);
参数说明:
- 如果不指定参数(参数为空,则查询该集合中所有文档)
- query:查询条件
- projection:该参数可以指定查询结果中需要显示的字段,设置为1,表示显示,为0,则不显示。"_id"字段默认显示。当设置"_id"为1时,其他字段必须为1,否则报错。
查询name等于zhangsan,age等于20的文档:
db.user.find({‘name‘:‘zhangsan‘,‘age‘:20})
比较操作符
- 小于 $lt
- 小于等于 $lte
- 大于 $gt
- 大于等于 $gte
- 不等于$ne
- 等于 $eq
- 包含 $in
- 不包含 $nin
查询age小于22的文档
db.user.find({‘age‘:{‘$lt‘:22}})
查询age大于等于22的文档
db.user.find({‘age‘:{‘$gte‘:22}})
查询age不等于23的文档:
db.user.find({‘age‘:{‘$ne‘:23}})
查询name值为wj或为zhangsan的文档:
db.user.find({‘name‘:{‘$in‘:[‘wj‘,‘zhangsan‘]}})
字母比较:
按照字母顺序比较:查询name第一个字符比x小的文档
db.user.find({‘name‘:{‘$lt‘:‘x‘}})
逻辑操作符
总共4种,不过多介绍:$and,$nor,$or,$not
查询name不是wj的文档:
db.user.find({‘name‘:{‘$not‘:{‘$eq‘:‘wj‘}}})
findOne
查询符合条件的第一个文档(自然排序),参数与find方法一样
db.user.findOne({‘name‘:{‘$lt‘:‘x‘}})
pretty格式化
使用pretty()方法可以格式化查询返回结果,知道有这一个方法就好,我的查询器默认已经格式化了。
findOne()默认会格式化返回结果,所以无需加上pretty()。
db.collection.find().pretty();
复杂查询条件
并列条件:查询age大于等于22,小于等于24的文档
db.user.find({‘age‘:{‘$gte‘:22, ‘$lte‘:24}})
或者条件:查询age大于等于22、小于等于24,或者name等于zhangsan的文档
对于这种,语法格式如下:
# db.collection.find({‘$or‘:[{},{}...]})
db.user.find({‘$or‘:
[
{‘name‘:‘zhangsan‘}
,{‘age‘:{‘$gte‘:22, ‘$lte‘:24}}
]
})
$type查询
根据集合中某个属性的类型查询对应的数据,使用$type指定属性类型
例如:查询name属性为字符串的文档
db.user.find({‘name‘:{‘$type‘:‘string‘}})
在mongodb中,数字类型默认都是double
db.user.find({‘age‘:{‘$type‘:‘double‘}})
$type有效值如下
type | number | Alias |
---|---|---|
Double | 1 | double |
String | 2 | string |
Object | 3 | object |
Array | 4 | array |
Binary data | 5 | binData |
Undefined | 6 | undefined |
ObjectId | 7 | objectId |
Boolean | 8 | bool |
Date | 9 | date |
Null | 10 | null |
Regular Expression | 11 | regex |
DBPointer | 12 | dbPoint |
JavaScript | 13 | javascript |
Symbol | 14 | symbol |
JavaScript(with scope) | 15 | javascriptWithScope |
32-bit integer | 16 | int |
Timestamp | 17 | timestamp |
64-bit integer | 18 | long |
Decimal128 | 19 | decimal |
正则查询
简写
语法:
db.collection.find({field:/pattern/})
查询name中以z开头的文档
db.user.find({‘name‘:/^z/})
查询name中以n结尾的文档:
db.user.find({‘name‘:/n$/})
查询name中以z开头、以n结尾的文档(.* 意为多个任意字符)
db.user.find({‘name‘:/^z.*n$/})
查询name中包含w字符的文档
db.user.find({‘name‘:/wj/})
查询name中包含w字符(忽略大小写)
db.user.find({‘name‘:/w/i})
差不多了解以上的正则在实际开发中就够用了,那些需要邮箱正则、手机号正则的场景,为什么不在插入数据之前就做处理呢?
全写
语法:
db.collection.find({field:{$regex:/pattern/,$options:‘<options>‘}})
db.collection.find({field:{$regex:/pattern/<options>}})
部分操作符也支持正则表达式
例如:查询name以z开头,或以n结尾的文档
db.user.find({‘name‘:{‘$in‘:[/^z/,/n$/]}})
查询name不以z开头的文档
db.user.find({‘name‘:{‘$not‘:/^z/}})
分页查询
结合limit()和skip()方法完成分页
limit:限制多少条返回
skip:跳过前多少条,并返回
查询第一页数据,一页三条(查询三条,跳过零条)
db.user.find().limit(3).skip(0);
db.user.find().limit(3);
查询第二页数据,一页三条(查询三条,跳过三条)
db.user.find().limit(3).skip(3);
不跳过任何数据,只查询前三条
db.user.find().limit(3);
跳过前三条数据,查询剩余所有数据
db.user.find().skip(3);
有点像mysql的limit n,m 跳过n行查询m行
排序查询
使用sort()方法即可排序
# age列的升序
db.user.find().sort({‘age‘:1});
# age列的降序
db.user.find().sort({‘age‘:-1});
# 先age升序,再name降序
db.user.find().sort({‘age‘:1,‘name‘:-1});
更新文档
mongodb主要通过save(覆盖)和update(修改)来更新文档。
save
save的作用是保存文档,如果文档存在则覆盖,不存在则插入。save对文档的存在判断标准是"_id"是否存在。所以如果想用save去更新文档,则必须带上该字段,且该字段在集合中已经存在。
db.user.save({"_id" : ObjectId("5ffac1b0a1761355478cf855"),‘name‘:‘lisi‘,‘age‘:19});
使用save,如果文档不存在并新增成功,则nUpserted为1,如果存在并修改成功,则nModified为1
update
该方法可以通过特定条件来更新一个或多个文档。
语法格式(其实后面可以携带更多参数,这里仅简单介绍基本用法):
db.collection.update(<query>,<update>);
参数说明:
- query 更新文档的筛选条件
- update 更新的字段和字段值
覆盖修改
把name等于wj的文档,变为age等于23(注意,update默认情况下只覆盖匹配到的第一条文档)
db.user.update({‘name‘:‘wj‘},{‘age‘:23})
上图为覆盖后的结果,name字段丢失了,是因为没有写name字段,直接用{‘age‘:23}覆盖了原来的文档
表达式更新
$set
把name等于wj的文档的age修改为25(这里也修改匹配到的第一条文档)
db.user.update({‘name‘:‘wj‘},{‘$set‘:{‘age‘:25}})
这里$set的字段,如果字段存在,则修改字段,如果不存在,则添加字段
$inc
将字段增加指定的值
把name等于wj的文档的age增加10
db.user.update({‘name‘:‘wj‘},{‘$inc‘:{‘age‘:10}})
$unset
把对应的字段删除
把name等于wj的文档的age删除
#age字段的值任意写,这里只是一个占位标记
db.user.update({‘name‘:‘wj‘},{‘$unset‘:{‘age‘:1}})
$push
这里先给name等于wj的文档添加一个字段courses课程,该字段是一个数组
db.user.update({‘name‘:‘wj‘},{‘$set‘:{‘courses‘:[‘springboot‘,‘springcloud‘]}})
现在我想向courses字段中添加一个元素docker
db.user.update({‘name‘:‘wj‘},{‘$push‘:{‘courses‘:‘docker‘}})
注意:以下的写法不是添加多个元素,而是往courses字段中添加了一个数组,所以push只能往数组中添加一个元素(无论是该元素数组还是其他)
db.user.update({‘name‘:‘wj‘},{‘$push‘:{‘courses‘:[‘jenkins‘,‘harbor‘]}})
如果push的字段不存在,则会新增一个字段,将元素放在数组中
db.user.update({‘name‘:‘wj‘},{‘$push‘:{‘course‘:[‘springboot‘,‘springcloud‘]}})
$addToSet
与push类似,该表达式也会向数组中添加元素,如果该元素存在,则不添加否则添加进入数组。
元素的匹配大小写敏感。
db.user.update({‘name‘:‘wj‘},{‘$addToSet‘:{‘courses‘:‘springboot2‘}})
$pop
出栈(删除出来的数据),与push(压栈)相反
#删除courses数组的最后一个元素
db.user.update({‘name‘:‘wj‘},{‘$pop‘:{‘courses‘:1}})
#删除courses数组的第一个元素
db.user.update({‘name‘:‘wj‘},{‘$pop‘:{‘courses‘:-1}})
$pull
推(删除指定元素)
#删除courses数组中所有名称为docker的元素
db.user.update({‘name‘:‘wj‘},{‘$pull‘:{‘courses‘:‘docker‘}})
$pullAll
推(删除多个指定元素)
db.user.update({‘name‘:‘wj‘},{‘$pullAll‘:{‘courses‘:[‘docker‘,‘springcloud‘]}})
执行前:
执行后:
$rename
修改字段名
# 将name=wj的文档中,字段名从name修改为user_name
db.user.update({‘name‘:‘wj‘},{‘$rename‘:{‘name‘:‘user_name‘}})
upset和multi
db.collection.update(<query>,<update>,<upset:boolean>,<multi:boolean>);
对于update方法,还有两个参数可以选择,upset和multi
- upset:默认为false,为true时,则表示在更新条件没有匹配时,会插入此文档,为false则不插入。
- multi:默认为false,为true时,会更新所有匹配到的文档,为false,则会更新匹配到的第1个文档。
#将所有name=wj的文档的age修改为25
db.user.update({‘name‘:‘wj‘},{‘$set‘:{‘age‘:25}},false,true)
# db.user.update({‘name‘:‘wj‘},{‘age‘:23},false,true) 该写法错误,多行操作不支持覆盖修改
删除文档
remove(不推荐)
删除所有age大于等于28的文档
db.user.remove({‘age‘:{‘$gte‘:28}});
删除第一条age大于等于20的文档
db.user.remove({‘age‘:{‘$gte‘:20}},true);
deleteOne
该方法只能删除匹配到的第一个文档
删除第一个age大于等于28的文档
db.user.deleteOne({‘age‘:{‘$gte‘:28}});
deleteMany
一次性删除所有匹配到的文档
删除所有age大于等于28的文档
db.user.deleteMany({‘age‘:{‘$gte‘:28}});