1. db.collection.update(query, update, options)
1.1 作用:
修改集合中的一个或多个文档,根据更新参数,该方法可以修改一个或多个文档中的特定字段的值,或完全替换现有文档 。
1.2 语法:
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string> // Available starting in MongoDB 4.2
}
)
1.3 参数说明
范围 | 类型 | 描述 |
---|---|---|
query | document | 使用查询运算符指定条件。和find()方法,一样的查询条件 |
update | 文档或管道 | 要修改的内容,以下三者之一。1. 更新操作符表达式的文档(json对象);2.替换的文档(
|
upsert | 布尔值 | 可选的。如果设置为true,则在没有文档符合查询条件时会创建一个新文档。默认值为 false,在找不到匹配项时,不插入文档。 |
multi | 布尔值 | 可选。如果设置为true,则更新满足query条件的多个文档。如果设置为false,则更新一个文档。默认值为false |
writeConcern | document | 可选, MongoDB写入安全机制,如果在事务中运行,请不要为操作明确设置writeConcern |
collation | document | 可选, 允许用户为字符串比较指定特定于语言的规则,例如字母大写和重音符号的规则 |
arrayFilters | array of document | 可选。过滤文档数组,在更新数组字段时,用于确定要进行更新的数组元素。 |
hint | Document or string | 可选的。一个文档或字符串,它指定支持查询谓词的索引。该选项可以是索引说明文档(json),或索引名称字符串。如果指定的索引不存在,则操作错误。 |
1.4 行为表现
# 1. 在分片集合上使用 multi: false, 匹配条件必须准确匹配 _id 字段,或指定单一的分片(如,通过包含 shard key)
# 2. 当db.collection.update()执行更新操作(而不是文档替换操作)时, db.collection.update()可以针对多个分片
# 3. 从MongoDB 4.2开始,替换文档操作首先尝试使用查询过滤条件来针对单个分片。如果无法通过查询过滤条件定位到单个分片,则它将尝试以替换文档定位。
# 4. 分片集合上的操作(更新文档,替换文档(v4.2之后)),db.collection.update()使用 upsert:true,在filter中必须包含完整的分片键shard key
# 但是,从版本4.4开始,分片集合中的文档可能会 缺少分片键字段。要定位缺少分片键的文档,可以将null 做相等条件匹配,并与另一个过滤条件(例如_id字段)结合使用,如:{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key
# 5.从MongoDB 4.2开始,你可以更新文档的shard key值,除非shard key字段是不可变的_id字段。在MongoDB 4.2之前,一个文档的shard key字段值是不可变的。
# 更新存在的shard key:你必须运行在 mongos 上,不能直接在分片上执行操作。必须在事务中执行或作为可重试的方式写入。必须指定multi: false。查询条件必须包含一个 使用完整shard key的相等条件匹配(<shardKey>: keyValue)
# 设置不存在的shard key: 你必须运行在 mongos 上,不能直接在分片上执行操作。如果设置成 null, 可以指定 multi: true,且如果 upsert: true ,则在匹配条件中需有 shard key 的相等条件。
# 如果设置成 非null , 必须在事务中执行或作为可重试的方式写入,必须指定multi: false。 如果 upsert: true, 或者 使用替换文档且设置值为另一个分片的shard key,则在匹配条件中需有 shard key 的相等条件
1.5 例子
##准备数据
db.books.remove({});
db.books.insertMany([
{
"_id" : 1,
"item" : "TBD",
"stock" : 0,
"info" : { "publisher" : "1111", "pages" : 430 },
"tags" : [ "technology", "computer" ],
"ratings" : [ { "by" : "ijk", "rating" : 4 }, { "by" : "lmn", "rating" : 5 } ],
"reorder" : false
},
{
"_id" : 2,
"item" : "XYZ123",
"stock" : 15,
"info" : { "publisher" : "5555", "pages" : 150 },
"tags" : [ ],
"ratings" : [ { "by" : "xyz", "rating" : 5 } ],
"reorder" : false
}
]);
###1. 使用更新运算符
## 如果更新内容使用了运算表达式,那就必须全部是运算符表达式。运用了运算符表达式的更新操作,只更新update()方法中出现的字段的值(增量更新)
## 以下出现了 $inc, $set操作符,且只更新 _id = 1的文档中的 stock, item, info.publisher, tags ratings[1],而 reorder 未更新
db.books.update(
{ _id: 1 }, #条件
{
$inc: { stock: 5 }, # 增加: stock + 5
$set: { # 设置值,如果某个字段不存在,则会添加进去
item: "ABC123",
"info.publisher": "2222",
tags: [ "software" ],
"ratings.1": { by: "xyz", rating: 3 } # ratings.1,设置 ratings[1]
}
}
)
## $push 更新操作符 ratings 数组 添加数据
db.books.update(
{ _id: 2 },
{
$push: { ratings: { "by" : "jkl", "rating" : 2 } }
}
)
## $unset 操作符,删除 tags 字段
db.books.update( { _id: 1 }, { $unset: { tags: 1 } } )
### 2. update 只使用 field:value 键值对
## 使用 键值对 的 更新内容,会完全替换匹配到的文档,除了 _id,即 全量更新
## 使用键值对,不能更新多个文档
## 更新后, 该文档内容: _id =2 , item = "XYZ123", info={ publisher: "2255", pages: 150 }, tags = [ "baking", "cooking" ]
## ratings 和 reorder 不存在了
db.books.update(
{ _id: 2 },
{
item: "XYZ123",
stock: 10,
info: { publisher: "2255", pages: 150 },
tags: [ "baking", "cooking" ]
}
)
### 3. 使用管道 更新
## 从MongoDB 4.2开始,该db.collection.update()方法可以接受一个聚合管道数组 [ <stage1>, <stage2>, ... ]。管道可以包括以下阶段:
##$addFields 及其别名 $set
##$project 及其别名 $unset
##$replaceRoot及其别名$replaceWith。
## 使用聚合管道可以实现更具表达力的更新语句,例如根据当前字段值表达条件更新,或使用另一个字段的值更新一个字段。
## 准备数据
db.members.insertMany([
{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 2, "misc1" : "note to self: confirm status", "misc2" : "Need to activate", "lastUpdate" : ISODate("2019-01-01T00:00:00Z") },
{ "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment", "lastUpdate" : ISODate("2019-01-01T00:00:00Z") }
])
#使用文档中其他字段的值修改字段
#1、$set 阶段: 添加新comments字段,修改lastUpdate字段的值。 comments的值为 misc1 和 misc2 字段组成的数组。 lastUpdate 的值 设为 聚合变量NOW的值 使用聚合变量方式:。$$ + 变量名
#2、$unset阶段: 删除集合中所有文档的misc1和misc2字段
db.members.update(
{ },
[
{ $set: { status: "Modified", comments: [ "$misc1", "$misc2" ], lastUpdate: "$$NOW" } },
{ $unset: [ "misc1", "misc2" ] }
],
{ multi: true }
)
## 准备数据
db.students3.insert([
{ "_id" : 1, "tests" : [ 95, 92, 90 ], "lastUpdate" : ISODate("2019-01-01T00:00:00Z") },
{ "_id" : 2, "tests" : [ 94, 88, 90 ], "lastUpdate" : ISODate("2019-01-01T00:00:00Z") },
{ "_id" : 3, "tests" : [ 70, 75, 82 ], "lastUpdate" : ISODate("2019-01-01T00:00:00Z") }
]);
##使用聚合管道,可以使用计算出的平均成绩和字母成绩来更新文档。
db.students3.update(
{ },
[
{ $set: { average : { $trunc: [ { $avg: "$tests" }, 0 ] }, lastUpdate: "$$NOW" } },
{ $set: { grade: { $switch: {
branches: [
{ case: { $gte: [ "$average", 90 ] }, then: "A" },
{ case: { $gte: [ "$average", 80 ] }, then: "B" },
{ case: { $gte: [ "$average", 70 ] }, then: "C" },
{ case: { $gte: [ "$average", 60 ] }, then: "D" }
],
default: "F"
} } } }
],
{ multi: true }
)
##更新后
{ "_id" : 1, "tests" : [ 95, 92, 90 ], "lastUpdate" : ISODate("2020-01-24T17:29:35.340Z"), "average" : 92, "grade" : "A" }
{ "_id" : 2, "tests" : [ 94, 88, 90 ], "lastUpdate" : ISODate("2020-01-24T17:29:35.340Z"), "average" : 90, "grade" : "A" }
{ "_id" : 3, "tests" : [ 70, 75, 82 ], "lastUpdate" : ISODate("2020-01-24T17:29:35.340Z"), "average" : 75, "grade" : "C" }
2. db.collection.updateOne(filter, update, options)
2.1 作用:
根据筛选条件更新集合中匹配到的第一个文档
2.2 语法:
db.collection.updateOne(
<filter>,
<update>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string> // Available starting in MongoDB 4.2.1
}
)
2.3 参数说明
参考 update() 方法,但 <update> 更新内容,不能是键值对形式(即不能替换文档),只能是更新操作符表达式 和 聚合管道 中的一种
2.4 行为表现
# 在分片集合上更新 ,如果 upsert: true,需要在filter中必须指定完整的分片键shard key。如果不指定 upsert: true,必须 精准匹配 _id 字段 或者 指定一个分片(如,通过在匹配条件中加入 shard key)
# 不兼容 db.collection.explain()
# 其他 参考 update() 方法行为表现的 第 4 、5 条
2.5 例子
# 部分例子可参考 update() 方法,除替换文档
##准备数据
db.students.insert([
{ "_id" : 1, "grades" : [ 95, 92, 90 ] },
{ "_id" : 2, "grades" : [ 98, 100, 102 ] },
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
])
# 使用 arrayFilters 和 位置操作符 $[<identifier>]
# 要修改grade数组中的所有元素,条件是 元素大于或等于100
db.students.updateOne(
{ grades: { $gte: 100 } },
{ $set: { "grades.$[element]" : 100 } },
{ arrayFilters: [ { "element": { $gte: 100 } } ] }
)
# 结果 更新单个文档
{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] } # 修改
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
##准备数据
db.students2.insert([
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 90, "std" : 4 },
{ "grade" : 85, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
])
#使用 arrayFilters 和 位置操作符 $[<identifier>]
# 修改grades 数组中的所有 对象的mean,条件是该对象的grade 大于等于 85
db.students2.updateOne(
{ },
{ $set: { "grades.$[elem].mean" : 100 } },
{ arrayFilters: [ { "elem.grade": { $gte: 85 } } ] }
)
# 结果
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 100, "std" : 4 }, # 修改
{ "grade" : 85, "mean" : 100, "std" : 6 } # 修改
]
}
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
3、 db.collection.updateMany(filter, update, options)
3.1 作用:
更新集合中匹配到的所有文档
3.2 语法:
db.collection.updateMany(
<filter>,
<update>,
{
upsert: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string> // Available starting in MongoDB 4.2.1
}
)
3.3 参数说明
参考 update() 方法,但 <update> 更新内容,不能是键值对形式(即不能替换文档),只能是更新操作符表达式 和 聚合管道 中的一种
3.4 行为说明
不兼容 db.collection.explain()
参考 update()
3.5 例子
参考 update(), updateOne()
update() , updateOne() , updateMany() 总体上的用法是一致的。区别是update()包含了 updateOne() updateMany() 的功能,且还有替换文档的功能
官网详情:
https://docs.mongodb.com/manual/reference/method/db.collection.update/
https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/
https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/
查询操作符:https://docs.mongodb.com/manual/reference/operator/query/
更新操作符:https://docs.mongodb.com/manual/reference/operator/update/
管道操作符:https://docs.mongodb.com/manual/reference/operator/aggregation/