MongoDB基础篇-06-文档操作

文章目录

  • 1. 简述
  • 2. 插入文档
    • 2.1 插入单个文档
    • 2.2 插入多个文档
  • 3. 更新文档
    • 3.1 `update`函数
  • 4. 更新操作符
    • 4.1 `$set操作符`
    • 4.2 `$inc操作符`
    • 4.3 `$unset操作符`
    • 4.4 `$push操作符`
    • 4.5 `$pop操作符`
    • 4.6 `$pull操作符`
    • 4.7 `$pullAll操作符`
    • 4.8 `$rename`
  • 5. 删除文档
    • 5.1 remove()函数
    • 5.2 deleteOne()函数
    • 5.3 deleteMany()函数
    • 5.4 删除集合中的所有文档
  • 6. 查询文档
    • 6.1 find()函数
    • 6.2 投影操作
    • 6.3 findOne()函数
    • 6.4 正则查询
  • 7. 条件操作符
    • 7.1 `$gt`
    • 7.2 `$lt`
    • 7.3 `$eq`
    • 7.4 `$ne`
    • 7.5 `$gte`
    • 7.6 `$lte`
    • 7.7 `$in`
    • 7.8 `$nin`
  • 8. 逻辑操作符
    • 8.1 `$and`
    • 8.2 `$or`
    • 8.3 `$and与$or联合使用`
  • 9. 类型操作符
    • 9.1`$type` 操作符
    • 9.2`$exists`
  • 10. 分页
  • 11. 排序
  • 12. 聚合查询
    • 12.1 求和 `$sum`
    • 12.2 取总和
    • 12.3 分组后取总和
    • 12.4 条件筛选 - $match
    • 12.5 最大值 - $max
    • 12.6 最小值 - $min
    • 12.7 平均值 - $avg
    • 12.8 统计结果返回数组 - $push
    • 12.9 数组字段拆分 - $unwind

1. 简述

在MongoDB中文档是指多个键及其关联的值有序地放置在一起就是文档,其实指的就是数据,也是我们平时操作最多的部分。
MongoDB中的文档的数据结构和 JSON 基本一样。所有存储在集合中的数据都是 BSON 格式。
BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。

2. 插入文档

2.1 插入单个文档

注意:

  • 新增时不需要考虑field,如果field已经存在则向指定field中新增。如果field不存在,则在collection中新添加一个filed
  • 向collection中新增数据时,如果collection不存在,则自动创建collection,向dev集合中插入单个文档。

可以使用insert/insertOne/save执行新增,语法完全相同:

db.c1.insert({name:"张三"});
db.c1.save({name:"张三"});
db.c1.insertOne({name:"张三"});

区别:

  • 当明确给定主键时,如果主键值已经存在save表示修改(全量替换),insert/insertOne会报主键重复。
    命令中_id是ObjectId类型,需要通过ObjectId函数把字符串转换为ObjectId

    db.c1.save({_id:ObjectId(“5e81b3ac4d4d000026004f6a”),name:“jqk”})

2.2 插入多个文档

可以使用insert/insertMany/save执行新增,区别于单条新增把新增函数参数由对象类型({})变成数组类型([{}])下面是三种写法等效:

db.c1.insert([{name:"a"},{name:"b"}]);
db.c1.insertMany([{name:"a"},{name:"b"}]);
db.c1.save([{name:"a"},{name:"b"}]);

3. 更新文档

MongoDB通过update函数或者save函数来更新集合中的文档;

3.1 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":"新名字"});

4. 更新操作符

db.集合名.update({条件},{更新逻辑},{"multi":true|false,"upsert":true|false});

  • multi: 是否批量更新多行数据。默认false
  • upsert: 更新逻辑匹配失败后,是否新增数据。默认false

4.1 $set操作符

$set操作符用来指定一个键并更新键值,若键不存在并创建。只能修改第一个document
语法格式: db.集合名.update({查询条件},{更新操作符:{更新内容}})
$set的作用总结:

  • 只修改特定的Field,解决update默认修改整个document情况

    db.c1.update({name:“张三”},{$set:{name:“王五”}});

  • 默认只修改符合条件的第一个document,如果需要全部修改,添加更新参数multi:true

    db.c1.update({name:“张三”},{$set:{age:18}},{multi:true});

  • 如果Field不存在,可以新建一个Field

    db.c1.update({name:“张三”},{$set:{sex:“男”}})

  • 如果没有,那么是张三的数据,则新增一条数据,age是18。

    db.c1.update({name:“张三”},{$set:{age:18}},{upsert:true, multi:true});

4.2 $inc操作符

$inc操作符可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作
如果给定正数表示新增,如果给定负数表示减少。
eg: 把王五的年龄减少5岁

db.c1.update({name:“王五”},{$inc:{age:-5}});

4.3 $unset操作符

$unset操作符:主要是用来删除键。让键的值为空。在编写命令时KaTeX parse error: Expected '}', got 'EOF' at end of input: …e({name:"王五"},{unset:{address:“随意”}});

4.4 $push操作符

$push操作符:向文档的某个数组类型的键添加一个数组元素,不过滤重复的数据。
添加时键存在,要求键值类型必须是数组;键不存在,则创建数组类型的键。

eg: db.c1.update({},{$push:{hobby:“写代码”}},{multi:true});

向集合c1中所有文档对象添加了数组类型属性hobby,并添加一个值写代码。如果再次执行,表示向hobby中再添加一个值写代码。默认只修改符合条件的第一条,如果需要全部修改,添加multi属性。

4.5 $pop操作符

$pop操作符:删除数据元素。可取值只能是1或-1。1表示尾部删除-1表示头部删除

eg: db.c1.update({name:“李四”},{$pop:{hobby:-1}})

删除hobby中第一个元素。其中$pop中key是要操作的数组类型属性。

4.6 $pull操作符

$pull操作符:从数组中删除满足条件的元素,只要满足条件都删除。

eg: db.c1.update({name:“王五”},{$pull:{hobby:“好好学习”}});

删除hobby中元素内容为好好学习,如果存在多个都删除。

4.7 $pullAll操作符

$pullAll操作符:可以设置多个条件。

eg: db.c1.update({name:“王五”},{$pullAll:{hobby:[“写代码”,“好好学习”]}});

删除王五中hobby为写代码和好好学习的值。其中属性(hobby)取值一定要是数组类型。

4.8 $rename

$rename操作符:对键进行重新命名。任何类型的键都能重命名

eg: db.c1.update({name:“王五”},{$rename:{name:“username”}});

修改王五的name属性为username。

5. 删除文档

5.1 remove()函数

语法格式:remove({指定删除条件},删除参数(可选参数))

使用remove()函数可删除集合中的指定文档
删除参数可取值:

  • 省略:删除满足条件的全部文档
  • 0:删除满足条件的全部文档
  • 其他数字:删除满足条件的第一条。

删除age为空的第一条数据

db.c1.remove({age:{$exists:false}},1);

删除所有age为空的数据。

db.c1.remove({age:{$exists:false}});

5.2 deleteOne()函数

deleteOne()函数是官方推荐删除文档的方法。该方法只删除满足条件的第一条文档。

删除age为18的第一个文档对象

db.c1.deleteOne({age:18});

5.3 deleteMany()函数

deleteMany函数是官方推荐的删除方法。该方法删除满足条件的所有数据。

删除所有age为18的文档对象。

db.c1.deleteMany({age:18});

5.4 删除集合中的所有文档

当remove和deleteMany条件设置为空时表示删除全部

  • remove({})
  • deleteMany({})

6. 查询文档

6.1 find()函数

在MongoDB中可以使用find()函数查询文档。
语法格式为:find({查询条件(可选)},{指定投影的键(可选)})

如果未给定参数则表示查询所有数据
db.c1.find();

查询所有name为张三的文档对象

db.c1.find({name:“张三”})

6.2 投影操作

投影查询指的就是哪些列被显示或不被显示。
写到投影(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})

6.3 findOne()函数

findOne()函数只返回满足条件的第一条数据。

返回第一行document对象。

db.c1.findOne();

返回名字为张三的第一条数据

db.c1.findOne({name:“张三”})

6.4 正则查询

MongoDB中查询条件也可以使用正则表达式作为匹配约束。正则表达式语法与JavaScript正则表达式语句完全相同。
正则内容需要写在 / / 之前。

语法格式:db.集合名字.find({字段名:正则表达式});

查询name中存在三的文档对象

db.c1.find({name:/三/});

或者 db.COLLECTION_NAME.find({字段名:{$regex:正则表达式,$options:正则选项}});

正则选项:

  • i - 不区分大小写以匹配大小写的情况。
  • m - 多行查找,如果内容里面不存在换行符号(例如 \n)或者条件上没有(start/end),该选项没有任何效果
  • x - 设置x选项后,正则表达式中的非转义的空白字符将被忽略。需要 r e g e x 与 regex与 regexoptions语法
  • s - 允许点字符(即.)匹配包括换行符在内的所有字符。需要 r e g e x 与 regex与 regexoptions语法
  • i,m,x,s可以组合使用。

7. 条件操作符

条件操作符用于比较两个表达式并从mongoDB集合中获取数据。
语法格式:find({键:{操作符:条件}})或者findOne({键:{操作符:条件}})

7.1 $gt

(>) 大于操作符,greater than 缩写。

查询所有年龄大于10的文档对象

db.c1.find({age:{$gt:10}});

7.2 $lt

(<) 小于操作符。less than缩写,用left记忆,左角括号

查询所有年龄小于10的文档对象

db.c1.find({age:{$lt:10}});

7.3 $eq

(==)等于操作符,equals

查询年龄等于8

db.c1.find({age:{$eq:8}});

等效于

db.c1.find({age:8});

7.4 $ne

(!=)不等操作符 not equals

查询所有年龄不是18岁的,包含了age属性没有值的文档对象。

db.c1.find({age:{$ne:8}});

7.5 $gte

(>=)大于或等于操作符greater than equals

查询所有年龄大于等于8的文档对象。如果文档没有age属性无法被查询。

db.c1.find({age:{$gte:8}});

7.6 $lte

(<=)小于或等于操作符less than equals

查询小于等于8的文档对象。

db.c1.find({age:{$lte:8}});

7.7 $in

我们可以使用$in操作符来表示多条件查询, i n 中多条件的关系为或者关系,只要满足其中一个就能被查询出来,由于 in中多条件的关系为或者关系,只要满足其中一个就能被查询出来,由于 in中多条件的关系为或者关系,只要满足其中一个就能被查询出来,由于in取值为多个,所以是数组类型。

查询年龄为8或10或12的文档对象

db.c1.find({age:{$in:[8,10,12]}})

7.8 $nin

not in,与$in的结果取反。

只要age不是8或10或12的文档对象都能查询出来。

db.c1.find({age:{$nin:[8,10,12]}})

8. 逻辑操作符

8.1 $and

我们可以使用$and操作符来表示多条件间的并且关系。
由于$and有多个条件,所以类型是数组类型[],每个元素都是一个条件{}

语法格式为:find({$and:[{条件一},{,条件二},.......]})

查询所有年龄为18,并且名字为张三的文档对象

db.c1.find({$and:[{age:18},{name:“张三”}]})

8.2 $or

我们可以使用$or操作符来表示多条件间的或者关系。

语法格式为:find({$or:[{条件一},{条件二},.....]})

查询所有年龄为18或8或姓名为张三的文档对象

db.c1.find({$or:[{age:18},{name:“张三”},{age:8}]})

8.3 $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}]}]});

9. 类型操作符

9.1$type 操作符

$type 根据类型查询。可取值和JavaScript类型取值相同。
$type的取值为类型别名,类型别名就是类型的全小写名称。

  • number 数值
  • string 字符串,注意s小写
  • object 对象
  • array 数组类型

取出所有age里面是数值类型的文档对象

db.c1.find({age:{$type:“number”}});

9.2$exists

可以借助$exists判断为空值的文档对象。

db.c1.find({age:{$exists:false}});

10. 分页

limit(数字)查询结果中前几个
skip(数字)跳过结果中前几个

跳过2个文档对象

db.c1.find().skip(2)

只要结果中前两行

db.c1.find().limit(2)

表示查询前两个文档对象,可用用在分页上,表示第一页数据。

db.c1.find().skip(0).limit(2)

11. 排序

在 MongoDB 中使用 sort() 函数对查询到的文档进行排序,sort() 函数可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列

语法格式:db.集合名称.find().sort({排序键:1})

查询结果按照age升序排序。

db.c1.find().sort({age:1});

也可以对字符串进行排序,排序时按照编码顺序进行排序。支持中文等。虽然支持,但是平时还是多按照数值类型的属性进行排序。

db.c1.find().sort({name:1});

12. 聚合查询

在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

12.1 求和 $sum

举例: 查询dev集合中一共有多少个文档。
相当于sql语句:

SELECT  count(*) AS count  FROM  c1

db.c1.aggregate([{$group:{_id:null,count:{$sum:1}}}])
  • $group:分组,代表聚合的分组条件
  • _id:分组的字段,是必须有的。相当于SQL分组语法group by column_name中的column_name部分。如果根据某字段的值分组,则定义为_id:‘$字段名’。如果没有分组属性取值为null
  • count:返回结果字段名。可以自定义,类似SQL中的字段别名。
  • $sum:如果取值为1表示总条数,相当于每个document中都多个count属性,count取值为1,累加和就是总条数。如果$sum取值是‘$field名’(要注意有单引号或双引号),表示对该field求累加和
  • 如果只有$group时 agregate()里面[]可以省略,因为就一个操作符。

12.2 取总和

$sum取值必须是字符串类型,有双引号。age是属性名,前面必须有$

db.c1.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …null,totalAge:{sum:“$age”}}}]);

12.3 分组后取总和

_id取值也是字符串类型,里面必须是属性名前面加上$

db.c1.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"name",totalAge:{ s u m : " sum:" sum:"age"}}}]);

12.4 条件筛选 - $match

$match和$group同级操作符,需要写在两个条件中的。

  • 写在$group前面
    $match写在$group前面表示先过滤条件,在分组。
    先查询出age大于等于5的文档对象,在按照name属性进行分组,计算age列总和
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}}}]);

12.5 最大值 - $max

$max可以计算最大值。

db.c1.aggregate([{$group:{_id:"$name",maxAge:{$max:"$age"}}}]);

12.6 最小值 - $min

$min可以计算最小值

db.c1.aggregate([{$group:{_id:"$name",minAge:{$min:"$age"}}}]);

12.7 平均值 - $avg

计算出不同姓名的平均年龄

db.c1.aggregate([{$group:{_id:"$name",avgAge:{$avg:"$age"}}}]);

12.8 统计结果返回数组 - $push

分组后按照分组数组进行合并,如果希望看到某个列合并之前的所有数据可以使用$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"}}}])

12.9 数组字段拆分 - $unwind

$unwind会把数组列进行拆分,原来的document会根据数组属性值个数分为多个document。如果这个数组属性为空,对应document将不被显示(因为document没有数组属性)
正常数据:只有name为abc的hobby有数组类型值,且长度为3

执行下面命令

db.c1.aggregate([{ u n w i n d : " unwind:" unwind:"hobby"}]);

你可能感兴趣的:(MongoDb基础篇,mongodb,数据库,database)