mongodb @aggregation 返回字段映射不上_MongoDB---基于分布式文件存储的数据库(二)...

f270bebb0f5bb161da312138bda29105.png

MongoDB基础入门到高级进阶视频教程

【MongoDB】

六、Document 操作

在MongoDB中文档是指多个键及其关联的值有序地放置在一起就是文档,其实指的就是数据,也是我们平时操作最多的部分。

MongoDB中的文档的数据结构和 JSON 基本一样。所有存储在集合中的数据都是 BSON 格式。

BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。

1. 新增文档

1.1 新增单一文档

1.1.1 insert函数

语法格式为:db.COLLECTION_NAME.insert(document)。

向test集合中插入单个文档。

db.test.insert({title:'北京尚学堂',description:'程序员的摇篮',url:'www.bjsxt.com',tags:['java','大数据','python'],'time':new ISODate('2020-01-01T10:10:10.000Z')})

1.1.2 save函数

向test集合中插入单个文档。

db.test.save({title:'百战程序员',description:'身经百战,高薪相伴',url:'www.itbaizhan.cn',tags:['javaWeb实战','数据库实战','微服务实战']})

1.1.3 insertOne函数

在MongoDB3.2以后的版本中,提供了insertOne()函数用于插入文档。

向test集合中插入单个文档。

db.test.insertOne({title:'尚学堂大数据',description:'培养大数据人才的摇篮',url:'www.bjsxt.com',tags:['hadoop','spark','Hbase']})

1.2 批量新增文档

1.2.1 insert函数

向test集合中批量插入多个文档

db.test.insert([{title:'java',tags:['JavaSE','JavaEE','JavaME']},{title:'ORM',tags:['Mybatis','Hibernate']},{title:'Spring',tags:['SpringMVC','SpringBoot','SpringCloud']}])

1.2.2 save函数

向test集合中批量插入多个文档

db.test.save([{title:'java',tags:['JavaSE','JavaEE','JavaME']},{title:'ORM',tags:['Mybatis','Hibernate']},{title:'Spring',tags:['SpringMVC','SpringBoot','SpringCloud']}])

1.2.3 insertMany函数

在MongoDB3.2以后的版本中,提供了insertMany函数用于插入文档。

语法格式:db.COLLECTION_NAME.insertMany([{},{},{},.....])

向test集合中批量插入多个文档

db.test.insertMany([{title:'java',tags:['JavaSE','JavaEE','JavaME']},{title:'ORM',tags:['Mybatis','Hibernate']},{title:'Spring',tags:['SpringMVC','SpringBoot','SpringCloud']}])

1.3 通过变量新增文档

Mongo Shell工具允许我们定义变量。所有的变量类型为var类型。也可忽略变量类型。变量中赋值符号后侧需要使用小括号来表示变量中的值。我们可以将变量作为任意插入文档的函数的参数。

语法格式:变量名=(<变量值>)

1.3.1 变量新增单一文档

定义变量

document=({title:'SpringCloud',tags:['Spring Cloud Netflix','Spring Cloud Security','Spring Cloud Consul']})

新增文档

db.test.insert(document);

db.test.save(document);

db.test.insertOne(document);

1.3.2 变量批量新增文档

定义变量

document=([{title:'SpringCloud',tags:['Spring Cloud Netflix','Spring Cloud Security','Spring Cloud Consul']},{title:'SpringBoot',tags:['Spring Boot']}])

新增文档

db.test.insert(document);

db.test.save(document);

db.test.insertMany(document);

2 查询文档

MongoDB是通过findOne()和find()函数来实现文档查询的。

2.1 基础应用

2.1.1 findOne函数

findOne函数用于查询集合中的一个文档。语法如下:

db.集合名称.findOne({
<query>},
{<projection>
});

参数解释:

  • query:可选,代表查询条件。
  • projection:可选,代表查询结果的投影字段名。即查询结果需要返回哪些字段或不需要返回哪些字段。

查询stu集合中第一个文档:

db.stu.findOne();

db.stu.findOne({});

查询stu集合中name字段为lisi的第一个文档:

db.stu.findOne({'name':'lisi'});

查询stu集合中第一个文档,且只显示name字段:

db.stu.findOne({},{'name':1});

查询stu集合中第一个文档,且不显示name和age字段:

db.stu.findOne({},{'name':0,'age':0});

注意:在projection中不能使用{'name':0, 'age':1}这种语法格式,这是错误的语法。projection只能定义要返回的字段或不返回的字段。_id字段是MongoDB维护的字段,是唯一可以在projection中独立使用的。如:{_id:0, 'name':1, 'age':1}

2.1.2 find函数

find函数用于查询集合中的若干文档。语法如下:

db.stu.find({<query>},{<projection>});

参数解释:

query:可选,代表查询条件。

projection:可选,代表查询结果的投影字段名。即查询结果需要返回哪些字段或不需要返回哪些字段。

查询stu集合中的所有文档:

db.stu.find()

db.stu.find({})

查询stu集合中所有name字段为lisi的文档:

db.stu.find({'name':'lisi'});

2.1.3 投影约束

在MongoDB中,_id字段是默认返回显示的投影字段。

查询stu集合中所有文档,且只显示name字段:

db.stu.find({},{'name':1});

查询stu集合中所有文档,且显示除name字段以外的其他字段:

db.stu.find({},{'name':0});

非_id字段,在投影约束中不能互斥,否则抛出异常。如:{"name":1, "age":0}抛出异常。

包含_id字段,在投影约束中可以和其他字段互斥约束,但是,_id字段必须为非投影显示约束(0),

如:{"name":1, "_id":0} 正确的。

包含_id字段,在投影约束中,如果和其他字段投影约束互斥,且_id字段投影约束为显示(1),会抛出异常,

如:{"_id":1, "name":0} 抛出异常。

常用方式: {"_id":0, "xxx":1} {"xxx":0}

总结:投影时,_id为1的时候,其他字段必须是1;_id是0的时候,其他字段可以是0;如果没有_id字段约束,多个其他字段必须同为0或同为1。

2.2 pretty函数

pretty函数用于格式化find函数查询结果。让查询结果更易查看。findOne函数自动附带格式化查询结果的能力。

语法:

db.stu.find().pretty();

2.3 单条件逻辑运算符

如果你熟悉常规的 SQL 数据,通过下表可以更好的理解 MongoDB 的条件语句查询:

d411ce98a90218bdde16b85d052f6156.png

在MongoDB中字符串也可以比较大小。按照Unicode编码顺序比较大小。

日期可以比较大小: 过往 < 现在 < 未来。

2.4 多条件逻辑运算符

2.4.1 And条件

MongoDB 的 find() 和 findOne() 函数可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。

查询stu集合中name字段为lisi,且age字段大于20的文档:

db.stu.find({'name':'lisi', 'age':{'$gt':20}});

2.4.2 Or条件

MongoDB OR 条件语句使用了关键字 $or,语法格式如下:

db.集合名称.find(
{
$or: [
{key1: value1}, {key2:value2}
]
}
)

查询stu集合中name字段为lisi或age字段大于22的文档:

db.stu.find({'$or':[{'name':'lisi'},{'age':{'$gt':22}}]});

2.4.3 And和Or的配合使用

查询集合stu中name字段为zhangsan,或name字段为lisi且age字段为22的文档。

db.stu.find({$or:[{'name': 'zhangsan'},{'name':'lisi', 'age':22}]});

2.5 $type查询

在MongoDB中根据字段的数量类型来查询数据使用$type操作符来实现,具体使用法语:

db.集合名.find({属性名:{$type:类型值}}) //这里的类型值能使用Number也能使用alias

$type的有效值如下:

56be7166a8a8edd9406d3d3a1c7791b2.png

查询stu集合中name字段类型为字符串的文档:

db.stu.find({'name':{$type:2}});

db.stu.find({'name':{$type:'string'}});

2.6 正则查询

MongoDB中查询条件也可以使用正则表达式作为匹配约束。

语法:

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

db.集合名称.find({字段名:{$regex:正则表达式[, $options:正则选项]}});

正则表达式格式:/xxx/

正则选项:

  • i - 不区分大小写以匹配大小写的情况。
  • m - 对于包含锚点的模式(即^对于开始, $对于结尾),在每行的开头或结尾处匹配具有多行值的字符串(可解析单字段中的换行符n)。如果没有此选项,这些锚点将在字符串的开头或结尾处匹配。
  • x - 设置x选项后,正则表达式中的非转义的空白字符将被忽略。需要$regex与$options语法
  • s - 允许点字符(即.)匹配包括换行符在内的所有字符。需要$regex与$options语法

i,m,x,s可以组合使用。

查询stu集合中name字段以'z'开头的数据

db.stu.find({'name':/^z/});

db.stu.find({'name':{$regex:/^z/}});

查询stu集合中name字段以'n'结尾的数据

db.stu.find({'name':/n$/});

db.stu.find({'name':{$regex:/n$/}});

查询stu集合中name字段中包含'a'的数据

db.stu.find({'name':/a/});

db.stu.find({'name':{$regex:/a/}});

查询stu集合中name字段以'L'开头的数据,且忽略大小写

db.stu.find({'name':/^L/i});

db.stu.find({'name':{$regex:/^L/i}});

db.stu.find({'name':{$regex:/^L/, $options:'i'}});

查询stu集合中remark字段以'A'开头的数据,且忽略大小写,同时增加锚点

db.stu.find({'name':/^L/im});

db.stu.find({'name':{$regex:/^L/im}});

db.stu.find({'name':{$regex:/^L/, $options:'im'}});

查询stu集合中name字段已'z'开头、'n'结尾的数据

db.stu.find({'name':/^z.*n$/});

db.stu.find({'name':{$regex:/^z.*n$/}});

查询stu集合中name字段以'z'或'l'开头的数据

db.stu.find({'name':{$in:[/^z/, /^l/]}});

查询stu集合中name字段不以'z'开头的数据

db.stu.find({'name':{$not:/^z/}});

查询stu集合中name字段不以'z'或'l'开头的数据

db.stu.find({'name':{$nin:[/^z/, /^l/]}});

2.7 分页查询

在MongoDB中,使用函数limit()和skip()来实现分页数据查询。

2.7.1 limit函数

在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。

语法:

db.集合名称.find().limit(查询数量);

查询stu集合中的前10条数据:

db.stu.find().limit(10);

不使用limit函数,默认查询集合中全部文档。如果limit函数不传递参数,也是查询集合中的全部文档。

2.7.2 skip函数

在MongoDB中使用skip()方法来跳过指定数量的文档,skip方法同样接受一个数字参数作为跳过的文档条数。

语法:

db.集合名称.find().[limit(查询数量).]skip(跳过数量);

查询stu集合第二条到最后一条的文档:

db.stu.find().skip(1);

db.stu.find().limit().skip(1);

假设每页查询文档数为2,现查询stu集合中第二页文档:

db.stu.find().limit(2).skip(2);

不使用skip函数,不会跳过任何文档,从集合的第一条文档开始查询。如果skip函数不传递参数,也是不跳过任何文档。

2.8 排序

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

语法:

db.集合名称.find().sort({key1:sortType1, key2:sortType2});

查询stu集合中全部文档,以age字段升序排列:

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

查询stu集合中全部文档,以age字段升序排列,如果age相同,则以name字段降序排列:

db.stu.find().sort({'age':1, 'name':-1});

3. 更新文档

MongoDB通过update函数与save函数来更新集合中的文档。

3.1 save更新文档

save()函数的作用是保存文档,如果文档存在则覆盖,如果文档不存在则新增。save()函数对文档是否存在的唯一判断标准是"_id"系统唯一字段是否匹配。所以使用save()函数实现更新操作,则必须提供"_id"字段数据。

save()函数的语法是:

db.集合名称.save(

<document>

);

参数document代表要修改的文档内容,要求必须提供"_id"字段数据。

使用save()函数实现更新操作:

db.test.save(

{

"_id" : ObjectId("5d0207e460ad10791be757d2"),

"title" : "MongoDB 教程",

"description" : "MongoDB 是一个 Nosql 数据库",

"by" : "北京尚学堂",

"tags" : [

"mongodb",

"NoSQL"

],

"likes" : 100

}

)

3.2 update更新文档

update() 函数用于更新已存在的文档。

语法格式:

db.集合名称.update(

<query>,

<update>,

< upsert:boolean>,

< multi:boolean>

)

参数说明:

query : update的查询条件,类似sql update更新语法内where后面的内容。

update : update的对象和一些更新的操作符等,也可以理解为sql update查询内set后面的。

upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入这个document,true为插入,默认是false,不插入。

multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。只有在表达式更新语法中才可使用。

在MongoDB中的update是有两种更新方式,一种是覆盖更新,一种是表达式更新。

覆盖更新:顾名思义,就是通过某条件,将新文档覆盖原有文档。

表达式更新:这种更新方式是通过表达式来实现复杂更新操作,如:字段更新、数值计算、数组操作、字段名修改等。

3.2.1 覆盖更新

通过update方法来更新一个完整的文档:

db.col.update(
{"title" : "MongoDB 教程"},
{
"title" : "MongoDB 教程",
"description" : "MongoDB 是一个 Nosql 数据库",
"by" : "北京尚学堂",
"likes" : 100
}
)

3.2.2 表达式更新

语法:

db.集合名称.update(
<query>,
<doc_projection>,
<upsert>,
<multi>
);

doc_projection语法:

{
$表达式:{具体更新规则}
}

① $inc

  • 用法:{$inc:{field:value}}
  • 作用:对一个数字字段的某个field增加value
  • 示例:将name为zhangsan的学生的age增加5
  • 命令:db.stu.update({name:"zhangsan"},{$inc:{age:5}})

② $set

  • 用法:{$set:{field:value}}
  • 作用:把文档中某个字段field的值设为value,如果field不存在,则增加新的字段并赋值为value。
  • 示例:把zhangsan的年龄设为23岁
  • 命令:db.stu.update({name:"zhangsan"},{$set:{'age':23}})

③ $unset

  • 用法:{$unset:{field:1}}
  • 作用:删除某个字段field
  • 示例:将zhangsan的年龄字段删除
  • 命令:db.stu.update({name:"zhangsan"},{$unset:{age:1}})

④ $push

  • 用法:{$push:{field:value}}
  • 作用:把value追加到field里。注:field只能是数组类型,如果field不存在,会自动插入一个数组类型
  • 示例:给zhangsan添加别名"xiaozhang"
  • 命令:db.stu.update({name:"zhangsan"},{$push:{"alias":"xiaozhang"}})

⑤ $addToSet

  • 用法:{$addToSet:{field:value}}
  • 作用:加一个值到数组内,而且只有当这个值在数组中不存在时才增加。
  • 示例:往zhangsan的别名字段里添加两个别名A1、A2
  • 命令:db.stu.update({name:"zhangsan"},{$addToSet:{"alias":["A1","A2"]}})

注意:此处加入的数据是一个数据为A1和A2的数组对象。并不是将两个数据依次加入alias数组中。

⑥ $pop

  • 用法:删除数组内第一个值:{$pop:{field:-1}}、删除数组内最后一个值:{$pop:{field:1}}
  • 作用:用于删除数组内的一个值
  • 示例:删除zhangsan记录中alias字段中最后一个别名
  • 命令:db.stu.update({name:"zhangsan"},{$pop:{"alias":1}})

⑦ $pull

  • 用法:{$pull:{field:_value}}
  • 作用:从数组field内删除所有等于_value的值
  • 示例:删除zhangsan记录中的别名xiaozhang
  • 命令:db.stu.update({name:"zhangsan"},{$pull:{"alias":"xiaozhang"}})

⑧ $pullAll

  • 用法:{$pullAll:value_array}
  • 作用:用法同$pull一样,可以一次性删除数组内的多个值。
  • 示例:删除zhangsan记录内的A1和A2别名
  • 命令:db.stu.update({name:"zhangsan"},{$pullAll:{"alias":["A1","A2"]}})

⑨ $rename

  • 用法:{$rename:{old_field_name:new_field_name}}
  • 作用:对字段进行重命名。底层实现是先删除old_field字段,再创建new_field字段。
  • 示例:把zhangsan记录的name字段重命名为sname
  • 命令:db.stu.update({name:"zhangsan"},{$rename:{"name":"sname"}})

⑩ 更多案例

  • 只更新第一条满足条件的记录:

db.col.update( { "count" : { $gt : 1 } } , { $set : { "test2" : "OK"} } );

  • 更新全部满足条件的记录:

db.col.update( { "count" : { $gt : 3 } } , { $set : { "test2" : "OK"} },false,true );

  • 如果没有符合条件的数据,则添加一条:

db.col.update( { "count" : { $gt : 4 } } , { $set : { "test5" : "OK"} },true,false );

  • 如果没有符合条件的数据,则全部添加进去:

db.col.update( { "count" : { $gt : 5 } } , { $set : { "test5" : "OK"} },true,true );

  • 只更新第一条记录:(等同第一个)

db.col.update( { "count" : { $lt : 10 } } , { $set : { "count" : 1} },false,false );

4. 删除文档

MongoDB是通过remove()函数、deleteOne()函数、deleteMany()函数来删除集合中的文档。

4.1 remove函数

语法格式是:

db.集合名称.remove(
<query>,
<justOne:boolean>
);

参数说明:

  • query:要删除的文档条件,相当于SQL语法中的where子句作用。
  • justOne:可选参数,布尔类型,代表是否只删除第一个匹配条件满足的文档。默认值为false,代表删除全部满足匹配条件的文档。

注意:此方法已经过时,官方推荐使用deleteOne()和deleteMany()函数来实现删除操作。且在4.0-版本中,remove()函数并不会真正的释放存储空间,需要使用db.repairDatabase()函数来释放存储空间。在4.2.1版本中,删除函数repairDatabase()。

4.1.1 删除全部

删除stus集合中的全部文档:

db.stus.remove({});

4.1.2 条件删除

  • 删除stus集合中age字段为10的文档。

db.stus.remove({'age':10});

  • 删除stus集合中age字段大于20的第一个文档。

db.stus.remove({'age':{'$gt':20}}, true);

  • 删除stus集合中age字段小于50的全部文档。

db.stus.remove({'age':{'$lt':50}});

db.stus.remove({'age':{'$lt':50}}, false);

4.2 deleteOne函数

语法格式:

db.集合名称.deleteOne({<query>});

参数解释:

query:要删除的文档条件,相当于SQL语法中的where子句作用。

删除stus集合中name字段为zhangsan的第一个文档:

db.stus.deleteOne({'name':'zhangsan'});

4.3 deleteMany函数

语法格式:

db.集合名称.deleteMany({<query>});

参数解释:

query:要删除的文档条件,相当于SQL语法中的where子句作用。

删除stus集合中age字段大于10的所有文档:

db.stus.deleteMany({'age':{'$gt':10}});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值