本文命令都是在 mongo shell 下实战的, 到了真实的 web 项目中这些命令对应的实现都是有封装的, 所以不用被吓到
先贴上官方正统文档 英文文档, 下面的链接都是中文社区的
MongoDB 更新文档的方法很多, 尤其是在 3.2 以后, 主要的方法有以下几种.
db.collection.updateOne() 即使可能有多个文档通过过滤条件匹配到, 但是也最多也只更新一个文档. 3.2 新版功能.
db.collection.updateMany() 更新所有通过过滤条件匹配到的文档. 3.2 新版功能.
db.collection.replaceOne() 即使可能有多个文档通过过滤条件匹配到, 但是也最多也只替换一个文档. 3.2 新版功能.
db.collection.update() 即使可能有多个文档通过过滤条件匹配到, 但是也最多也只更新或者替换一个文档. 默认情况下只更新 一个 文档. 要更新多个文档, 请使用 选项
db.collection.save() 通过传入的文档来替换已有文档.
本文只对 update()方法做说明, 其余几个放发内置了链接可以去看官方文档
update()语法
- db.collection.update(
- <filter>,
- <update>,
- {
- upsert: <boolean>,
- writeConcern: <document>,
- collation: <document>
- }
- )
参数说明:
query : update 的查询条件, 类似 sql update 查询内 where 条件.
update : update 的对象和一些更新的操作符 (如 $set,$inc...) 等, 也可以理解为 sql update 查询内 set 后面的
upsert : 可选, 这个参数的意思是, 如果不存在 update 的记录, 是否插入一条新的文档, true 为插入, 默认是 false, 不插入.
multi : 可选, MongoDB 默认是 false, 只更新找到的第一条记录, 如果这个参数为 true, 就把按条件查出来多条记录全部更新.
writeConcern : 可选, 抛出异常的级别.
update 过滤文档语法
1. 相等查询
{ <field1>: <value1>, <field2>: <value2>...}
表达式指定相等条件, 查询满足 <field> 等于 <value > 的所有文档, 可以指定多组条件
2. 查询操作符来指定查询条件
{ <field1>: { <operator1>: <value1> }, ... }
指定操作符查询条件需要嵌套{}, 如查询 age 字段大于 20 的
{"age" : {$gt: 20}}
我们接着上一篇文章来测试, 首先查看 users 文档的记录
- > db.users.find().pretty()
- {
- "_id" : ObjectId("5c77461437955b945af7321f"),
- "name" : "缘来是你",
- "age" : 27,
- "gender" : "male"
- }
- {
- "_id" : ObjectId("5c77499137955b945af73220"),
- "name" : "tom",
- "age" : 22,
- "gender" : "male"
- }
- {
- "_id" : ObjectId("5c77499137955b945af73221"),
- "name" : "Linda",
- "age" : 18,
- "gender" : "female"
- }
- {
- "_id" : ObjectId("5c77731d37955b945af73222"),
- "name" : "Hanmeimei",
- "age" : 17,
- "gender" : "female"
- }
- {
- "_id" : ObjectId("5c7774b736397a1c0aa425ea"),
- "name" : "Jack",
- "age" : 42,
- "gender" : "male"
- }
- {
- "_id" : ObjectId("5c7774b736397a1c0aa425eb"),
- "name" : "Lucy",
- "age" : 23,
- "gender" : "female"
- }
pretty()方法可以在终端美化输出结果
我们将 tom 的 age 改为 20
- > db.users.update({
- "name" : "tom"
- }, {
- $set : {
- "age" : 20
- }
- })
- WriteResult({
- "nMatched" : 1, "nUpserted" : 0, "nModified" : 1
- })
- > db.users.find()
- {
- "_id" : ObjectId("5c77461437955b945af7321f"), "name" : "缘来是你", "age" : 27, "gender" : "male"
- }
- {
- "_id" : ObjectId("5c77499137955b945af73220"), "name" : "tom", "age" : 20, "gender" : "male"
- }
- {
- "_id" : ObjectId("5c77499137955b945af73221"), "name" : "Linda", "age" : 18, "gender" : "female"
- }
- {
- "_id" : ObjectId("5c77731d37955b945af73222"), "name" : "Hanmeimei", "age" : 17, "gender" : "female"
- }
- {
- "_id" : ObjectId("5c7774b736397a1c0aa425ea"), "name" : "Jack", "age" : 42, "gender" : "male"
- }
- {
- "_id" : ObjectId("5c7774b736397a1c0aa425eb"), "name" : "Lucy", "age" : 23, "gender" : "female"
- }
这里就不用 pretty()方法美化了, 篇幅太长
看第二条文档, tom 的年龄被改为了 20
将 Jack 和 Lucy 的年龄改为 25 该怎么做呢, 先来个错误命令
- > db.users.update({
- "name" : {
- $in : ["Jack", "Lucy"]
- }
- }, {
- $set: {
- "age" : 25
- }
- })
- WriteResult({
- "nMatched" : 1, "nUpserted" : 0, "nModified" : 1
- })
- > db.users.find()
- {
- "_id" : ObjectId("5c77461437955b945af7321f"), "name" : "缘来是你", "age" : 27, "gender" : "male"
- }
- {
- "_id" : ObjectId("5c77499137955b945af73220"), "name" : "tom", "age" : 20, "gender" : "male"
- }
- {
- "_id" : ObjectId("5c77499137955b945af73221"), "name" : "Linda", "age" : 18, "gender" : "female"
- }
- {
- "_id" : ObjectId("5c77731d37955b945af73222"), "name" : "Hanmeimei", "age" : 17, "gender" : "female"
- }
- {
- "_id" : ObjectId("5c7774b736397a1c0aa425ea"), "name" : "Jack", "age" : 25, "gender" : "male"
- }
- {
- "_id" : ObjectId("5c7774b736397a1c0aa425eb"), "name" : "Lucy", "age" : 23, "gender" : "female"
- }
问题: 只有 Jack 的年龄被更新为 25 而 Lucy 的没有, 前面说了 update()只更新匹配到的第一条记录, 要想更新多条需要设置 multi 参数. 来看下一条命令
- > db.users.update({
- "name" : {
- $in : ["Jack", "Lucy"]
- }
- }, {
- $set: {
- "age" : 28
- }
- }, {
- multi : true
- })
- WriteResult({
- "nMatched" : 2, "nUpserted" : 0, "nModified" : 2
- })
- > db.users.find()
- {
- "_id" : ObjectId("5c77461437955b945af7321f"), "name" : "缘来是你", "age" : 27, "gender" : "male"
- }
- {
- "_id" : ObjectId("5c77499137955b945af73220"), "name" : "tom", "age" : 20, "gender" : "male"
- }
- {
- "_id" : ObjectId("5c77499137955b945af73221"), "name" : "Linda", "age" : 18, "gender" : "female"
- }
- {
- "_id" : ObjectId("5c77731d37955b945af73222"), "name" : "Hanmeimei", "age" : 17, "gender" : "female"
- }
- {
- "_id" : ObjectId("5c7774b736397a1c0aa425ea"), "name" : "Jack", "age" : 28, "gender" : "male"
- }
- {
- "_id" : ObjectId("5c7774b736397a1c0aa425eb"), "name" : "Lucy", "age" : 28, "gender" : "female"
- }
这里加了 {multi: true} 参数, 所以 Jack 和 Lucy 的 age 都被设置成了 28. 如果更新的文档不存在呢? 我们尝试一下将 upsert 设置为 true, 来看下一条命令
- > db.users.update({"name":"Lucys"}, {$set : {"is_active": 0}}, {upsert: true})
- WriteResult({
- "nMatched" : 0,
- "nUpserted" : 1,
- "nModified" : 0,
- "_id" : ObjectId("5c77946b96c95d22dfe8b411")
- })
- > db.users.find()
- { "_id" : ObjectId("5c77461437955b945af7321f"), "name" : "缘来是你", "age" : 27, "gender" : "male" }
- { "_id" : ObjectId("5c77499137955b945af73220"), "name" : "tom", "age" : 20, "gender" : "male" }
- { "_id" : ObjectId("5c77499137955b945af73221"), "name" : "Linda", "age" : 18, "gender" : "female" }
- { "_id" : ObjectId("5c77731d37955b945af73222"), "name" : "Hanmeimei", "age" : 17, "gender" : "female" }
- { "_id" : ObjectId("5c7774b736397a1c0aa425ea"), "name" : "Jack", "age" : 28, "gender" : "male" }
- { "_id" : ObjectId("5c7774b736397a1c0aa425eb"), "name" : "Lucy", "age" : 28, "gender" : "female" }
- { "_id" : ObjectId("5c77946b96c95d22dfe8b411"), "name" : "Lucys", "is_active" : 0 }
可以看到这里 MongoDB 新增了一条文档, 而且除了_id 字段外, 其余的字段都出现在了更新语句中, 没出现的在文档中没有. 对于 upsert 和 multi 参数你也可以这么设置
- > db.users.update({
- "age": {
- $gt: 25
- }
- }, {
- $set: {
- "is_active": 1
- }
- }, false, true)
- WriteResult({
- "nMatched" : 3, "nUpserted" : 0, "nModified" : 3
- })
- > db.users.find()
- {
- "_id" : ObjectId("5c77461437955b945af7321f"), "name" : "缘来是你", "age" : 27, "gender" : "male", "is_active" : 1
- }
- {
- "_id" : ObjectId("5c77499137955b945af73220"), "name" : "tom", "age" : 20, "gender" : "male"
- }
- {
- "_id" : ObjectId("5c77499137955b945af73221"), "name" : "Linda", "age" : 18, "gender" : "female"
- }
- {
- "_id" : ObjectId("5c77731d37955b945af73222"), "name" : "Hanmeimei", "age" : 17, "gender" : "female"
- }
- {
- "_id" : ObjectId("5c7774b736397a1c0aa425ea"), "name" : "Jack", "age" : 28, "gender" : "male", "is_active" : 1
- }
- {
- "_id" : ObjectId("5c7774b736397a1c0aa425eb"), "name" : "Lucy", "age" : 28, "gender" : "female", "is_active" : 1
- }
- {
- "_id" : ObjectId("5c77946b96c95d22dfe8b411"), "name" : "Lucys", "is_active" : 0
- }
第一个参数 false 是 upsert 的值, 第二个 true 是 multi 的值
来源: http://www.jianshu.com/p/308b6cc2d485