在MongoDB中文档是指多个键及其关联的值有序地放置在一起就是文档,其实指的就是数据,也是我们平时操作最多的部分。
MongoDB中的文档的数据结构和 JSON 基本一样。所有存储在集合中的数据都是 BSON 格式。
BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。
注意:
可以使用insert
/insertOne
/save
执行新增,语法完全相同:
db.c1.insert({name:"张三"});
db.c1.save({name:"张三"});
db.c1.insertOne({name:"张三"});
区别:
db.c1.save({_id:ObjectId(“5e81b3ac4d4d000026004f6a”),name:“jqk”})
可以使用insert
/insertMany
/save
执行新增,区别于单条新增把新增函数参数由对象类型({})
变成数组类型([{}])
下面是三种写法等效:
db.c1.insert([{name:"a"},{name:"b"}]);
db.c1.insertMany([{name:"a"},{name:"b"}]);
db.c1.save([{name:"a"},{name:"b"}]);
MongoDB通过update函数或者save函数来更新集合中的文档;
update
函数update() 函数用于更新已存在的文档。
语法格式:db.集合名称.update({查询条件},{更新内容},{更新参数(可选)})
其中更新内容为整个文档更新内容,如果更新内容中只有一个属性,除了_id以外其他属性将会被设置null。
> db.ccc.insert({name:"张三",age:12,address:"地址"})
WriteResult({ "nInserted" : 1 })
> db.ccc.update({name:"张三"},{name:"李四"})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.ccc.find()
{ "_id" : ObjectId("61ab4c9ab9e3376040bf2476"), "k1" : "v1" }
{ "_id" : ObjectId("61ab981e19453644a04231ff"), "name" : "李四" }
>
如图所示,修改name改成了李四,age和address都被设置null了。(mongodb中如果一个集合中某个属性所有的文档对象都为空时会删除这个属性);
使用save函数更新,只能更新单条数据。批量更新会抛出异常。批量操作只能新增数据。
db.c1.save({"_id":ObjectId("xxxxx"), "name":"新名字"});
db.集合名.update({条件},{更新逻辑},{"multi":true|false,"upsert":true|false});
$set操作符
$set操作符
:用来指定一个键并更新键值,若键不存在并创建。只能修改第一个document
语法格式: db.集合名.update({查询条件},{更新操作符:{更新内容}})
$set的作用总结:
db.c1.update({name:“张三”},{$set:{name:“王五”}});
db.c1.update({name:“张三”},{$set:{age:18}},{multi:true});
db.c1.update({name:“张三”},{$set:{sex:“男”}})
db.c1.update({name:“张三”},{$set:{age:18}},{upsert:true, multi:true});
$inc操作符
$inc操作符
:可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作。
如果给定正数表示新增,如果给定负数表示减少。
eg: 把王五的年龄减少5岁
db.c1.update({name:“王五”},{$inc:{age:-5}});
$unset操作符
$unset操作符
:主要是用来删除键。让键的值为空。在编写命令时KaTeX parse error: Expected '}', got 'EOF' at end of input: …e({name:"王五"},{unset:{address:“随意”}});
$push操作符
$push操作符
:向文档的某个数组类型的键添加一个数组元素,不过滤重复的数据。
添加时键存在,要求键值类型必须是数组;键不存在,则创建数组类型的键。
eg: db.c1.update({},{$push:{hobby:“写代码”}},{multi:true});
向集合c1中所有文档对象添加了数组类型属性hobby,并添加一个值写代码。如果再次执行,表示向hobby中再添加一个值写代码。默认只修改符合条件的第一条,如果需要全部修改,添加multi属性。
$pop操作符
$pop操作符
:删除数据元素。可取值只能是1或-1。1表示尾部删除,-1表示头部删除
eg: db.c1.update({name:“李四”},{$pop:{hobby:-1}})
删除hobby中第一个元素。其中$pop中key是要操作的数组类型属性。
$pull操作符
$pull操作符
:从数组中删除满足条件的元素,只要满足条件都删除。
eg: db.c1.update({name:“王五”},{$pull:{hobby:“好好学习”}});
删除hobby中元素内容为好好学习,如果存在多个都删除。
$pullAll操作符
$pullAll操作符
:可以设置多个条件。
eg: db.c1.update({name:“王五”},{$pullAll:{hobby:[“写代码”,“好好学习”]}});
删除王五中hobby为写代码和好好学习的值。其中属性(hobby)取值一定要是数组类型。
$rename
$rename操作符
:对键进行重新命名。任何类型的键都能重命名
eg: db.c1.update({name:“王五”},{$rename:{name:“username”}});
修改王五的name属性为username。
语法格式:remove({指定删除条件},删除参数(可选参数))
使用remove()函数可删除集合中的指定文档
删除参数可取值:
删除age为空的第一条数据
db.c1.remove({age:{$exists:false}},1);
删除所有age为空的数据。
db.c1.remove({age:{$exists:false}});
deleteOne()函数是官方推荐删除文档的方法。该方法只删除满足条件的第一条文档。
删除age为18的第一个文档对象
db.c1.deleteOne({age:18});
deleteMany函数是官方推荐的删除方法。该方法删除满足条件的所有数据。
删除所有age为18的文档对象。
db.c1.deleteMany({age:18});
当remove和deleteMany条件设置为空时表示删除全部
在MongoDB中可以使用find()函数查询文档。
语法格式为:find({查询条件(可选)},{指定投影的键(可选)})
如果未给定参数则表示查询所有数据
db.c1.find();
查询所有name为张三的文档对象
db.c1.find({name:“张三”})
投影查询指的就是哪些列被显示或不被显示。
写到投影(projection)里面的属性可取值为1(显示)或0(不显示)。
除了_id以外其他属性取值必须是相同。
sex和hobby不显示,其他属性都显示
db.c1.find({name:“张三”},{sex:0,hobby:0})
显示sex和hobby,默认_id也是显示
db.c1.find({name:“张三”},{sex:1,hobby:1})
只显示sex和hobby。只有这种情况才能出现属性取值不一样
db.c1.find({name:“张三”},{_id:0,sex:1,hobby:1})
findOne()函数只返回满足条件的第一条数据。
返回第一行document对象。
db.c1.findOne();
返回名字为张三的第一条数据
db.c1.findOne({name:“张三”})
MongoDB中查询条件也可以使用正则表达式作为匹配约束。正则表达式语法与JavaScript正则表达式语句完全相同。
正则内容需要写在 / / 之前。
语法格式:db.集合名字.find({字段名:正则表达式});
查询name中存在三的文档对象
db.c1.find({name:/三/});
或者 db.COLLECTION_NAME.find({字段名:{$regex:正则表达式,$options:正则选项}});
正则选项:
条件操作符用于比较两个表达式并从mongoDB集合中获取数据。
语法格式:find({键:{操作符:条件}})或者findOne({键:{操作符:条件}})
$gt
(>) 大于操作符,greater than 缩写。
查询所有年龄大于10的文档对象
db.c1.find({age:{$gt:10}});
$lt
(<) 小于操作符。less than缩写,用left记忆,左角括号
查询所有年龄小于10的文档对象
db.c1.find({age:{$lt:10}});
$eq
(==)等于操作符,equals
查询年龄等于8
db.c1.find({age:{$eq:8}});
等效于
db.c1.find({age:8});
$ne
(!=)不等操作符 not equals
查询所有年龄不是18岁的,包含了age属性没有值的文档对象。
db.c1.find({age:{$ne:8}});
$gte
(>=)大于或等于操作符greater than equals
查询所有年龄大于等于8的文档对象。如果文档没有age属性无法被查询。
db.c1.find({age:{$gte:8}});
$lte
(<=)小于或等于操作符less than equals
查询小于等于8的文档对象。
db.c1.find({age:{$lte:8}});
$in
我们可以使用$in
操作符来表示多条件查询, i n 中多条件的关系为或者关系,只要满足其中一个就能被查询出来,由于 in中多条件的关系为或者关系,只要满足其中一个就能被查询出来,由于 in中多条件的关系为或者关系,只要满足其中一个就能被查询出来,由于in取值为多个,所以是数组类型。
查询年龄为8或10或12的文档对象
db.c1.find({age:{$in:[8,10,12]}})
$nin
not in,与$in
的结果取反。
只要age不是8或10或12的文档对象都能查询出来。
db.c1.find({age:{$nin:[8,10,12]}})
$and
我们可以使用$and
操作符来表示多条件间的并且关系。
由于$and
有多个条件,所以类型是数组类型[],每个元素都是一个条件{}
语法格式为:find({$and:[{条件一},{,条件二},.......]})
查询所有年龄为18,并且名字为张三的文档对象
db.c1.find({$and:[{age:18},{name:“张三”}]})
$or
我们可以使用$or
操作符来表示多条件间的或者关系。
语法格式为:find({$or:[{条件一},{条件二},.....]})
查询所有年龄为18或8或姓名为张三的文档对象
db.c1.find({$or:[{age:18},{name:“张三”},{age:8}]})
$and与$or联合使用
一定要从逻辑上分清楚总体是and还是or。
设置完成类似SQL:通过or分成两部分,每部分里面又是and条件
select * from c1 where name='张三' and age=18 or username='王五' and age=18
MongoDB命令:
db.c1.find({$or:[{$and:[{name:"张三"},{age:18}]},{$and:[{username:"王五"},{age:8}]}]});
$type
操作符$type 根据类型查询。可取值和JavaScript类型取值相同。
$type的取值为类型别名,类型别名就是类型的全小写名称。
取出所有age里面是数值类型的文档对象
db.c1.find({age:{$type:“number”}});
$exists
可以借助$exists判断为空值的文档对象。
db.c1.find({age:{$exists:false}});
limit(数字)查询结果中前几个
skip(数字)跳过结果中前几个
跳过2个文档对象
db.c1.find().skip(2)
只要结果中前两行
db.c1.find().limit(2)
表示查询前两个文档对象,可用用在分页上,表示第一页数据。
db.c1.find().skip(0).limit(2)
在 MongoDB 中使用 sort() 函数对查询到的文档进行排序,sort() 函数可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。
语法格式:db.集合名称.find().sort({排序键:1})
查询结果按照age升序排序。
db.c1.find().sort({age:1});
也可以对字符串进行排序,排序时按照编码顺序进行排序。支持中文等。虽然支持,但是平时还是多按照数值类型的属性进行排序。
db.c1.find().sort({name:1});
在MongoDB中我们可以通过aggregate()函数来完成一些聚合查询,aggregate()函数主要用于处理诸如统计,平均值,求和等,并返回计算后的数据结果。
语法格式:db.集合名称.aggregate([{$group:{_id:"$分组键名","$分组键名",.....,别名:{聚合运算:"$运算列"}}},{条件筛选:{键名:{运算条件:运算值}}}])
常见的mongo的聚合操作和mysql的查询做类比:
SQL操作/函数 | mongodb聚合操作 |
---|---|
where | $match |
group by | $group |
having | $match |
select | $project |
order by | $sort |
limit | $limit |
sum() | $sum |
count() | $sum |
join | $lookup |
$sum
举例: 查询dev集合中一共有多少个文档。
相当于sql语句:
SELECT count(*) AS count FROM c1
db.c1.aggregate([{$group:{_id:null,count:{$sum:1}}}])
$sum
:如果取值为1表示总条数,相当于每个document中都多个count属性,count取值为1,累加和就是总条数。如果$sum
取值是‘$field名’(要注意有单引号或双引号),表示对该field求累加和$sum取值必须是字符串类型,有双引号。age是属性名,前面必须有$
db.c1.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …null,totalAge:{sum:“$age”}}}]);
_id取值也是字符串类型,里面必须是属性名前面加上$
db.c1.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"name",totalAge:{ s u m : " sum:" sum:"age"}}}]);
$match和$group同级操作符,需要写在两个条件中的。
$match写在$group前面表示先过滤条件,在分组。
db.c1.aggregate([{$match:{age:{$gte:5}}},{$group:{_id:"$name",totalAge:{$sum:"$age"}}}]);
写在$group后面
分组后结果集只有_id和totalAge两个属性,所以在$match中只能对这个属性进行操作。
db.c1.aggregate([{$group:{_id:"$name",totalAge:{$sum:"$age"}}},{$match:{totalAge:{$gte:5}}}]);
$max
可以计算最大值。
db.c1.aggregate([{$group:{_id:"$name",maxAge:{$max:"$age"}}}]);
$min
可以计算最小值
db.c1.aggregate([{$group:{_id:"$name",minAge:{$min:"$age"}}}]);
计算出不同姓名的平均年龄
db.c1.aggregate([{$group:{_id:"$name",avgAge:{$avg:"$age"}}}]);
分组后按照分组数组进行合并,如果希望看到某个列合并之前的所有数据可以使用$push,把分组后同一组的所有值放到一个数组中
按照name进行分组,分组后把age的数据都放入到名称为allAge的数组中
db.c1.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"name",allAge:{ p u s h : " push:" push:"age"}}}])
$unwind会把数组列进行拆分,原来的document会根据数组属性值个数分为多个document。如果这个数组属性为空,对应document将不被显示(因为document没有数组属性)
正常数据:只有name为abc的hobby有数组类型值,且长度为3
执行下面命令
db.c1.aggregate([{ u n w i n d : " unwind:" unwind:"hobby"}]);