第一部分 更新文档
文档存入数据库之后,就可以采用Update来修改它的内容,
db.collection.update( #查询条件 <query>, #修改器 <update>, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> } )
参数说明:
query : update的查询条件,类似sql update查询内where后面的。 update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的 upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。 multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。 writeConcern :可选,抛出异常的级别。
1.1 创建与删除($set与$unset)
$set 用来指定一个键的值,如果这个键不存在就创建,否则就更新.
> db.users.find().pretty() { "_id" : ObjectId("58bfb2c61b0dbd8a36332275"), "name" : "Mongodb", "time" : 15, }
> db.users.update({"name":"Mongodb"}, {"$set": {"Other": "Nodejs"}}) > WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.users.find().pretty() { "_id" : ObjectId("58bfb2c61b0dbd8a36332275"), "name" : "Mongodb", "time" : 15, "Other" : "Nodejs"}
添加一个新的字段没有问题, 那么添加一个数组呢?? (当然添加字典也是没问题的,不在此演示)
> db.users.update({"name":"Mongodb"}, {"$set": {"Other": ["Mariadb", "Python"]}})
> db.users.find().pretty() { "_id" : ObjectId("58bfb2c61b0dbd8a36332275"), "name" : "Mongodb", "time" : 15, "Other" : [ "Mariadb", "Python" ] }
删除某个字段---$unset
> db.users.update({"name":"Mongodb"}, {"$unset": {"Other": 1}})
1.2 专职数字($inc)
$inc [increase: 增加] 修改器用来增加
已有的键的值,不存在则创建; 只能来增加或减少数字值, 数值可以设置为正负
来增加或减少, 仅此用于整数/长整数/双进度浮点数
> db.users.update({"name": "Mongodb"}, {"$inc": {"time": 100}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.users.find() { "_id" : ObjectId("58bfb2c61b0dbd8a36332275"), "name" : "Mongodb", "time" : 115 }
1.3 数组修改器($push)
如果在之前的数据中添加一个新的科目
, 并且存储一个数组中就可以采用**$push**
, 之前的$set直接覆盖
,那么$push是否会存在这种情况?
> db.users.update({"name": "Mongodb"}, {"$push": {"courses": {"name": "Nodejs", "credit": 10}}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.users.update({"name": "Mongodb"}, {"$push": {"courses": {"name": "Mariadb", "credit": 8}}})
结果
> db.users.find().pretty() { "_id" : ObjectId("58bfb2c61b0dbd8a36332275"), "name" : "Mongodb", "time" : 15, "courses" : [ { "name" : "Nodejs", "credit" : 10 }, { "name" : "MariaDB", "credit" : 8 } ] }
以上的做法实现了, 向数组中添加元素(不是替换), 但是问题是加入我不希望重复添加相同的数据, $push 就不能胜任了
接下来实现我们需求的就是 $addToSet
1.4 $addToSet 添加
不重复的将元素添加到集合中--$addTOSet
> db.users.update({"name": "Mongodb"}, {"$addToSet": {"courses": {"name": "Nodejs", "credit": 10}}}) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 }) > db.users.find().pretty() { "_id" : ObjectId("58bfb2c61b0dbd8a36332275"), "name" : "Mongodb", "time" : 15, "courses" : [ { "name" : "Nodejs", "credit" : 10 }, { "name" : "Nodejs", "credit" : 10 } ] }
$push 与 $addToSet的异同点:
同: 1. 同样可以向集合中添加数据, 字典数组; 不同: 1. $push可以插入同样的数据,结果同时存在 2. $addToSet会覆盖同样的数据
我们在添加一个属性----评价(evaluate)这个数组, 并将一个数组遍历的存入数据库
我们就可以采用$each与$addToSet结合使用
> db.users.update({"name": "Mongodb"}, {"$addToSet": {"evaluate": {"$each": ["good", "great", "nice"]}}})
结果如下
> db.users.find().pretty() { "_id" : ObjectId("58bfb2c61b0dbd8a36332275"), "name" : "Mongodb", "time" : 15, "courses" : [ ... ], "evaluate" : [ "good", "great", "nice" ] }
1.5 操作数组(删除$pop/$pull)
数组是无序的,如何删除特定的元素----第一个? 最后一个? 匹配的某一些?
如何达到所需要求,Mongodb给出了相应的关键字---$pop $pull
原先添加一些测试数据
> db.users.update({"name": "Mongodb"}, {"$push": {"evaluate": {"$each": ["good1", "good2", "nice1", "nice2"]}}}) > .... "evaluate" : [ "good", "great", "good1", "good2", "nice1", "nice2" ]
1.5.1 $pop 删除首尾数据
#最后一个> db.users.update({"name": "Mongodb"}, {"$pop": {"evaluate": 1}})#第一个> db.users.update({"name": "Mongodb"}, {"$pop": {"evaluate": -1}})
脑洞大开的话, 可以试试别的数字 -_-
1.5.2 $pull 删除匹配数据
> db.users.update({"name": "Mongodb"}, {"$pull": {"evaluate": "great"}})
在此会删除匹配的数据, 参数项不可为数组
1.5.2 操作指定位置的数组元素---$
源数据如下, 需求: 更改课程(courses)中,Nodejs的学分(credit)为99
> db.users.find().pretty() { "_id" : ObjectId("58bfb2c61b0dbd8a36332275"), "name" : "Mongodb", "time" : 15, "courses" : [ { "name" : "Nodejs", "credit" : 10 }, { "name" : "Mariadb", "credit" : 10 } ], ... }
提示: 数组下标是从0开始,并且数组名与对象key都有了
第一种: 依据数据下标, 结合$set, 拆找到指定元素就更改. 缺点: 前提是需要知道位置;
第二种使用MongoDB的关键字--$进行匹配, 注意:只可以更改第一个匹配的数据.
实例如下:
> db.users.update({"name": "Mongodb"}, {"$set": {"courses.0.credit": 100}} )
> db.users.update({"name": "Mongodb"}, {"$set": {"courses.$.credit": 100}} ) WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0, "writeError" : { "code" : 16837, "errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: courses.$.credit" } })
比着葫芦画瓢但是报错了!!!!
主要原因是update的查询条件返回的不是数组, 所以无法匹配更改
正确的做法为
#在此你会发现,查找项多了两个参数> db.users.update({"name" : "Mongodb","courses.name": "Nodejs"}, {"$set": {"courses.$.credit": 22}}) > db.users.find().pretty() { "_id" : ObjectId("58bfb2c61b0dbd8a36332275"), "name" : "Mongodb", "time" : 15, "courses" : [ { "name" : "Nodejs", "credit" : 22 }, { "name" : "MariaDB", "credit" : 10 } ], .... }
1.5.3 $pushAll添加所有项目
{ $pushAll: { <field>: [ <value1>, <value2>, ... ] } } { $push: { <field>: { $each: [ <value1>, <value2> ... ] } } }
> db.users.update({}, {"$pushAll": {"test": [1, 2, 3, 4, 2, 1, 3]}}) > db.users.find().pretty() { "_id" : ObjectId("58ca3706250b163ff8331604"), ....... "test" : [1,2,3,4,2,1,3] }
1.5.4 $pullAll删除所有匹配项
{ $pullAll: { <field1>: [ <value1>, <value2> ... ], ... } }
> db.users.update({}, {"$pullAll": {"test": [1, 2]}}) > db.users.find().pretty() { "_id" : ObjectId("58ca3706250b163ff8331604"), "name" : "Mongodb", ...... "test" : [ 3, 4, 3 ] }
1.5.5 $each与$addToSet/$push结合使用
{ $addToSet: { <field>: { $each: [ <value1>, <value2> ... ] } } } { $push: { <field>: { $each: [ <value1>, <value2> ... ] } } }
1.5.6 $slice
稍后更新1.5.7 $sort
稍后更新1.6 第三个参数---upsert
upsert : 如果不存在update的记录,true为插入,默认是false,不插入。(update+insert)
#在执行之前,只有一条数据,不存在{"name": "Nodejs"}> db.users.update({"name": "Nodejs"}, {"$set": {"time": 10}})#因为没有设置upsert, 没有匹配上,所以都是0WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })#设置upsert为TRUE, 即成功> db.users.update({"name": "Nodejs"}, {"$set": {"time": 10}}, true) WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : ObjectId("58ca96b56d72019e69b70823") })
如果再次执行下边的代码, 会在time基础之上+10
> db.users.update({"name": "Nodejs"}, {"$set": {"time": 10}}, true) WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
1.7 第四个参数---multi
之前的操作都是基于一个的操作,只匹配第一个,但是假如需要匹配多项, 那么就需要设置multi 参数为 true。
更新第一个credit, 如果存在在基础上加1, 否则创建该字段
> db.users.update({"name": "Mongodb"}, {"$inc": {"courses.0.credit": 1}}, true)
> db.users.update({"courses.name": "Nodejs"}, {"$inc": {"courses.$.credit": 10}}, true) >
添加一个新的数据
db.users.insert({"name": "Mongodb"})
现在有两条数据, name都为Mongodb
, 为每个name=Mongodb的数据添加一个字段为: "teacher: hhw".
> db.users.update({"name": "Mongodb"}, {"$set": {"teacher": "hhw"}}, false, true) > db.users.find().pretty() { "_id" : ObjectId("58c0f8141b0dbd8a364264b8"), "name" : "Mongodb", "teacher" : "hhw"} { "_id" : ObjectId("58c0f8421b0dbd8a364264b9"), "name" : "Mongodb", "time" : 10, "courses" : [ ... ], "evaluate" : [ ... ], "teacher" : "hhw"}
第二部分 删除文档
2.1 remove
只会删除集合users的文档,但是不会删除集合本身,原有的索引也会存在, 但是数据删除时永久性的, 不能撤销.
> db.users.remove();
2.2 deleteOne/deleteMany
db.collection.deleteOne()db.collection.deleteMany()
删除速度更快的可以采用drop_collections("users"), 速度很快但是,集合与索引都删除了.