更新
定义
update
的
update
命令用于修改集合中的文档。一个update
命令可以包含多个更新语句。提示
在
mongosh
中,此命令还可以通过以下方法运行:updateOne()
、updateMany()
、replaceOne()
、findOneAndReplace()
和findOneAndUpdate()
辅助方法.辅助方法对
mongosh
用户来说很方便,但它们可能不会返回与数据库命令相同级别的信息。在不需要方便性或需要额外返回字段的情况下,请使用数据库命令。
兼容性
此命令在以下环境中的部署中可用
MongoDB Atlas:云中MongoDB部署的全托管服务
注意
此命令在所有MongoDB Atlas集群中受支持。有关Atlas对所有命令的支持信息,请参阅不受支持的命令。
MongoDB Enterprise:基于订阅的、自行管理的MongoDB版本
MongoDB Community:源代码可用、免费使用且自行管理的MongoDB版本
语法
变更在版本5.0.
该命令有以下语法
db.runCommand( { update: <collection>, updates: [ { q: <query>, u: <document or pipeline>, c: <document>, // Added in MongoDB 5.0 upsert: <boolean>, multi: <boolean>, collation: <document>, arrayFilters: <array>, hint: <document|string> }, ... ], ordered: <boolean>, maxTimeMS: <integer>, writeConcern: { <write concern> }, bypassDocumentValidation: <boolean>, comment: <any>, let: <document> // Added in MongoDB 5.0 } )
命令字段
该命令包含以下字段
字段 | 类型 | 描述 | |||||
---|---|---|---|---|---|---|---|
更新 | string | 目标集合的名称。 | |||||
updates | array | 对指定集合执行的一个或多个更新语句的数组。有关更新语句的详细信息,请参阅更新语句。 | |||||
有序 | 布尔值 | 可选。如果 true ,则当更新语句失败时,不执行剩余的更新语句。如果false ,则当更新失败时,继续执行剩余的更新语句(如果有的话)。默认为true 。 | |||||
maxTimeMS | 非负整数 | 可选。 指定毫秒的时间限制。如果您未指定 MongoDB使用与 | |||||
writeConcern | 文档 | ||||||
bypassDocumentValidation | 布尔值 | 可选。启用 update 在操作期间绕过文档验证。这允许您更新不满足验证要求的文档。 | |||||
comment | 任何 | 可选。附加到此命令的用户提供的注释。一旦设置,此注释将在以下位置显示与该命令相关的记录:
注释可以是任何有效的BSON类型(字符串、整数、对象、数组等)。 | |||||
文档 | 可选。 指定包含变量列表的文档。这允许您通过将变量与查询文本分离来提高命令的可读性。 文档语法是
变量设置为表达式返回的值,之后无法更改。 要在命令中访问变量的值,请使用双美元符号前缀( 完整示例,请参阅 在 新在版本5.0. |
更新语句
updates
数组的每个元素都是一个更新语句文档。每个文档包含以下字段
字段 | 类型 | 描述 | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
文档 | ||||||||||||||||||||
文档或管道 | 要应用的修改。值可以是以下之一
有关详细信息,请参阅 行为。 | |||||||||||||||||||
文档 | 可选。只有当 u 是管道时,才能指定 指定包含变量列表的文档。这允许您通过将变量与查询文本分离来提高命令的可读性。 文档语法是
变量设置为表达式返回的值,之后无法更改。 要在命令中访问变量的值,请使用双美元符号前缀( 要使用变量来过滤结果,必须在 有关使用 新在版本5.0. | |||||||||||||||||||
布尔值 | 可选。当
如果同时设置了 为了避免多次 更新,请确保 默认为 | |||||||||||||||||||
multi | 布尔值 | 可选。如果设置为 在更新多个文档时,如果单个文档更新失败,则不会更新后续的文档。请参见 多更新失败 了解此行为的更多详细信息。 | ||||||||||||||||||
collation | 文档 | 可选。 指定操作中使用的 校对规则。 校对规则 允许用户指定特定于语言的字符串比较规则,例如字母大小写和重音符号的规则。 校对选项的语法如下
指定校对规则时, 如果未指定校对规则,但集合具有默认校对规则(请参阅 如果集合或操作未指定校对规则,MongoDB 使用之前版本中用于字符串比较的简单二进制比较。 您不能为操作指定多个校对规则。例如,您不能为每个字段指定不同的校对规则,或者如果在排序时执行查找,则不能为查找和排序使用不同的校对规则。 | ||||||||||||||||||
arrayFilters | array | 可选。一个过滤器文档数组,用于确定要修改数组字段的更新操作中哪些数组元素。 在更新文档中,使用
在更新文档中,您可以多次包含相同的标识符;然而,对于更新文档中每个不同的标识符(
但是,您可以在单个过滤器文档中对同一标识符指定复合条件,如下面的示例所示。
| ||||||||||||||||||
文档或字符串 | 可选。一个文档或字符串,用于指定用于支持索引以支持查询谓词。 该选项可以接受索引规范文档或索引名称字符串。 如果您指定了一个不存在的索引,则操作将出错。 有关示例,请参阅为 Update 操作指定 |
返回
该命令返回一个包含操作状态的文档。例如
{ "ok" : 1, "nModified" : 0, "n" : 1, "upserted" : [ { "index" : 0, "_id" : ObjectId("52ccb2118908ccd753d65882") } ] }
有关输出字段的详细信息,请参阅输出。
访问控制
在运行着 authorization
的部署上,用户必须拥有以下权限的访问权限
内置角色 readWrite
提供了所需的权限。
行为
使用更新操作表达式文档更新
更新语句字段 u 可以接受只包含 更新操作符 表达式的文档。例如
updates: [ { q: <query>, u: { $set: { status: "D" }, $inc: { quantity: 2 } }, ... }, ... ]
然后,update
命令只更新文档中的相应字段。
使用替换文档更新
更新语句字段 u 字段可以接受替换文档,即文档只包含 仅 field:value
表达式。例如
updates: [ { q: <query>, u: { status: "D", quantity: 4 }, ... }, ... ]
然后,update
命令会替换匹配的文档为更新文档。update
命令只能替换一个单个匹配文档;也就是说,multi
字段不能设置为true
。update
命令不会替换_id
值。
多文档更新失败
如果在更新命令中将multi
参数设置为true
,单个文档更新失败,则该命令将不会更新其他文档。
例如,创建一个包含以下文档的members
集合
db.members.insertMany( [ { "_id" : 1, "member" : "Taylor", "status" : "pending", "points" : 1}, { "_id" : 2, "member" : "Alexis", "status" : "enrolled", "points" : 59}, { "_id" : 3, "member" : "Elizabeth", "status" : "enrolled", "points" : 34} ] )
以下操作在members
集合上创建了一个文档验证器,规则是points
值不能等于60
。
db.runCommand( { collMod: "members", validator: { points: { $ne: 60 } } } )
此更新命令将每个文档的points
字段增加1
。
db.runCommand( { update: "members", updates: [ { q: {}, u: { $inc: { points: 1 } }, multi: true } ] } )
运行命令后,集合包含以下文档
{ _id: 1, member: 'Taylor', status: 'A', points: 2 } { _id: 2, member: 'Alexis', status: 'D', points: 59 } { _id: 3, member: 'Elizabeth', status: 'C', points: 34 }
更新命令更新了第一个文档的points
值,但未能更新第二个文档,因为验证器规则规定points
值不能等于60
。第三个文档未更新,因为没有其他文档在写入错误后更新。
注意
如果匹配的文档子集被更新,例如,当更新会导致某些文档失败模式验证时,update
命令返回的nModified
值可能不准确。
使用聚合管道更新
更新语句字段 u 字段可以接受一个 聚合管道 [ <阶段1>, <阶段2>, ... ]
,该管道指定要执行修改。管道可以由以下阶段组成
$addFields
和其别名$set
$replaceRoot
和其别名$replaceWith
使用聚合管道可以实现更丰富的更新语句,例如根据当前字段值表达条件更新或使用其他字段(的值)更新一个字段。
例如
updates: [ { q: <query>, u: [ { $set: { status: "Modified", comments: [ "$misc1", "$misc2" ] } }, { $unset: [ "misc1", "misc2" ] } ], ... }, ... ]
有关示例,请参阅 使用聚合管道更新。
使用唯一索引进行 Upsert
除非存在防止重复的唯一索引,否则 Upsert 可能会创建重复的文档。
考虑以下示例,没有名为 Andy
的文档,并且多个客户端几乎同时发出以下命令
db.runCommand( { update: "people", updates: [ { q: { name: "Andy" }, u: { $inc: { score: 1 } }, multi: true, upsert: true } ] } )
如果所有 update
操作在成功插入数据之前完成查询阶段,并且 name
字段上没有唯一索引,则每个 update
操作可能会导致插入,创建多个具有 name: Andy
的文档。
在 name
字段上创建唯一索引可以确保只创建一个文档。在有唯一索引的情况下,现在的多个 update
操作将表现出以下行为
只有一个
update
操作将成功插入一个新文档。其他
update
操作将更新新插入的文档或因唯一键冲突而失败。为了使其他
update
操作能够更新新插入的文档,必须满足以下所有条件目标集合有一个会导致重复键错误的唯一索引。
更新操作不是
updateMany
或multi
被设置为false
。更新匹配条件可以是以下之一
一个单独的等价谓词。例如
{ "fieldA" : "valueA" }
等价谓词的逻辑与。例如
{ "fieldA" : "valueA", "fieldB" : "valueB" }
等价谓词中的字段与唯一索引键模式中的字段匹配。
更新操作不会修改唯一索引键模式中的任何字段。
以下表格显示了在键冲突发生时,upsert
操作的示例,这些操作要么导致更新,要么失败。
唯一索引键模式 | 更新操作 | 结果 | ||||||
---|---|---|---|---|---|---|---|---|
|
| 匹配文档的 score 字段增加1。 | ||||||
|
| 操作失败,因为它修改了唯一索引键模式中的字段( name )。 | ||||||
|
| 操作失败,因为等价谓词字段( name 、email )与索引键字段(name )不匹配。 |
限制
对于 updates
数组中的每个更新元素,查询和更新的大小之和(即 q
和 u
)必须小于或等于最大BSON文档大小。
updates
数组中更新语句的总数必须小于或等于最大批量大小。
文档验证
命令 update
添加了对 bypassDocumentValidation
选项的支持,该选项允许您在向具有验证规则的集合插入或更新文档时跳过 文档验证。
分片集合
在分片集合上的 upsert
要在分片集合上使用 update
与 multi: false
,
如果您没有指定 upsert: true,则过滤器 q 必须包含对
_id
字段的等式匹配或针对单个分片(例如,通过包含分片键)。如果您指定了 upsert: true,则过滤器 q 必须包含对分片键的等式匹配。
然而,分片集合中的文档可能会缺少 分片键字段。要定位缺少分片键的文档,您可以使用
null
等式匹配与另一个过滤器条件(例如,对_id
字段的匹配)结合使用。例如{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key
替换文档
在替换文档时,update
首先尝试使用查询过滤器定位一个分片,如果无法通过查询过滤器定位单个分片,则尝试通过替换文档进行定位。
分片键修改
除非分片键字段是不可变的 _id
字段,否则您可以更新文档的分片键值。
要使用 update
:
提示
由于缺失的键值作为空等价匹配的一部分返回,为避免更新空值的键,请根据需要包含额外的查询条件(例如在 _id
字段上)。
另请参阅 upsert
在分片集合上的用法。
缺少分片键
分片集合中的文档可能缺少分片键字段。要使用 update
设置文档的 缺失 分片键,您必须在 mongos
上运行。不要在分片上直接执行此操作。
此外,以下要求也适用
任务 | 要求 |
---|---|
设置为 null |
|
设置为非- null 值 |
|
提示
由于缺失的键值作为空等价匹配的一部分返回,为避免更新空值的键,请根据需要包含额外的查询条件(例如在 _id
字段上)。
另请参阅
事务
重要
在大多数情况下,分布式事务相对于单文档写入会带来更高的性能成本,因此分布式事务的可用性不应替代有效的模式设计。对于许多场景,非规范化数据模型(嵌入文档和数组)将始终是最适合您的数据和用例。也就是说,对于许多场景,适当地建模您的数据可以最大限度地减少对分布式事务的需求。
关于事务使用的其他考虑因素(例如运行时限制和oplog大小限制),请参阅生产注意事项。
事务中的Upsert
如果事务不是跨分片写事务,则可以在分布式事务内部创建集合和索引。
update
命令使用upsert: true
可以在现有集合或不存在集合上运行。如果在不存在的集合上运行,该操作将创建该集合。
写关注和事务
如果在事务中运行操作,请不要显式设置操作的写入关注点。有关在事务中使用写入关注点的信息,请参阅事务和写入关注点。
示例
更新一个文档的特定字段
使用 更新运算符 仅更新文档的指定字段。
例如,创建一个包含以下文档的members
集合
db.members.insertMany([ { _id: 1, member: "abc123", status: "Pending", points: 0, misc1: "note to self: confirm status", misc2: "Need to activate" }, { _id: 2, member: "xyz123", status: "D", points: 59, misc1: "reminder: ping me at 100pts", misc2: "Some random comment" }, ])
以下命令使用 $set
和 $inc
更新运算符来更新 status
和 points
字段,其中 member
等于 "abc123"
的文档。
db.runCommand( { update: "members", updates: [ { q: { member: "abc123" }, u: { $set: { status: "A" }, $inc: { points: 1 } } } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
由于 <update>
文档没有指定可选的 multi
字段,因此即使有多个文档匹配 q
匹配条件,更新也只修改一个文档。
返回的文档显示,命令找到了并更新了一个文档。该命令返回
{ "n" : 1, "nModified" : 1, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
见 输出 以获取详细信息。
命令之后,集合包含以下文档
{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 1, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" } { "_id" : 2, "member" : "xyz123", "status" : "D", "points" : 59, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
更新多个文档的特定字段
使用更新运算符来更新文档中指定的字段,并在更新语句中将multi
字段设置为true
。
例如,一个members
集合包含以下文档
{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 1, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" } { "_id" : 2, "member" : "xyz123", "status" : "D", "points" : 59, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
以下命令使用$set
和$inc
更新运算符分别修改集合中所有文档的status
和points
字段。
db.runCommand( { update: "members", updates: [ { q: { }, u: { $set: { status: "A" }, $inc: { points: 1 } }, multi: true } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
该更新修改了与在q
字段中指定的查询匹配的所有文档,即匹配集合中所有文档的空查询。
返回的文档显示命令找到了并更新了多个文档。对于副本集,命令返回
{ "n" : 2, "nModified" : 2, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
见 输出 以获取详细信息。
命令之后,集合包含以下文档
{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 2, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" } { "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
使用聚合管道更新
update
命令可以使用聚合管道进行更新。该管道可以包含以下阶段
$addFields
和其别名$set
$replaceRoot
和其别名$replaceWith
使用聚合管道可以实现更丰富的更新语句,例如根据当前字段值表达条件更新或使用其他字段(的值)更新一个字段。
示例 1
以下示例使用聚合管道使用文档中其他字段的值来修改一个字段。
一个名为 members
的集合包含以下文档
{ "_id" : 1, "member" : "abc123", "status" : "A", "points" : 2, "misc1" : "note to self: confirm status", "misc2" : "Need to activate" } { "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
假设不是单独的 misc1
和 misc2
字段,而是将这些字段汇集到一个新的 comments
字段中。以下更新操作使用聚合管道添加新的 comments
字段,并从集合中的所有文档中删除 misc1
和 misc2
字段。
首先,将
status
字段设置为"Modified"
,并添加一个新的字段comments
,该字段包含两个其他字段misc1
和misc2
的当前内容。其次,删除
misc1
和misc2
字段。
db.runCommand( { update: "members", updates: [ { q: { }, u: [ { $set: { status: "Modified", comments: [ "$misc1", "$misc2" ] } }, { $unset: [ "misc1", "misc2" ] } ], multi: true } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
返回的文档显示,该命令找到了并更新了多个文档。该命令返回
{ "n" : 2, "nModified" : 2, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
见 输出 以获取详细信息。
命令之后,集合包含以下文档
{ "_id" : 1, "member" : "abc123", "status" : "Modified", "points" : 2, "comments" : [ "note to self: confirm status", "Need to activate" ] } { "_id" : 2, "member" : "xyz123", "status" : "Modified", "points" : 60, "comments" : [ "reminder: ping me at 100pts", "Some random comment" ] }
示例 2
聚合管道允许基于当前字段值执行条件更新,以及使用当前字段值来计算单独的字段值。
db.students.insertMany( [ { "_id" : 1, "tests" : [ 95, 92, 90 ] }, { "_id" : 2, "tests" : [ 94, 88, 90 ] }, { "_id" : 3, "tests" : [ 70, 75, 82 ] } ] );
使用聚合管道,您可以更新文档,包含计算出的平均成绩和成绩等级。
db.runCommand( { update: "students", updates: [ { q: { }, u: [ { $set: { average : { $avg: "$tests" } } }, { $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 } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
- 第一阶段
- 《$set》阶段根据
tests
字段的平均值计算一个新的字段average
。有关$avg
聚合运算符的更多信息,请参阅$avg
。 - 第二阶段
- 《$set》阶段根据上一阶段计算的
average
字段计算一个新的字段grade
。有关$switch
聚合运算符的更多信息,请参阅$switch
。
返回的文档显示,该命令找到了并更新了多个文档。该命令返回
{ "n" : 3, "nModified" : 3, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
命令之后,集合包含以下文档
{ "_id" : 1, "tests" : [ 95, 92, 90 ], "average" : 92.33333333333333, "grade" : "A" } { "_id" : 2, "tests" : [ 94, 88, 90 ], "average" : 90.66666666666667, "grade" : "A" } { "_id" : 3, "tests" : [ 70, 75, 82 ], "average" : 75.66666666666667, "grade" : "C" }
批量更新
以下示例在members
集合上执行多个更新操作
db.runCommand( { update: "members", updates: [ { q: { status: "P" }, u: { $set: { status: "D" } }, multi: true }, { q: { _id: 5 }, u: { _id: 5, name: "abc123", status: "A" }, upsert: true } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
返回的文档显示该命令修改了10
个文档并插入了一个具有_id
值为5
的文档。有关详细信息,请参阅输出。
{ "ok" : 1, "nModified" : 10, "n" : 11, "upserted" : [ { "index" : 1, "_id" : 5 } ] }
指定排序规则
校对规则 允许用户指定特定于语言的字符串比较规则,例如字母大小写和重音符号的规则。
集合myColl
有以下文档
{ _id: 1, category: "café", status: "A" } { _id: 2, category: "cafe", status: "a" } { _id: 3, category: "cafE", status: "a" }
以下操作包含排序规则选项
db.runCommand({ update: "myColl", updates: [ { q: { category: "cafe", status: "a" }, u: { $set: { status: "Updated" } }, collation: { locale: "fr", strength: 1 } } ] })
指定 arrayFilters
用于数组更新操作
当更新数组字段时,您可以指定 arrayFilters
来确定要更新的数组元素。
匹配 arrayFilters
条件的更新元素
创建一个包含以下文档的集合 students
db.students.insertMany( [ { "_id" : 1, "grades" : [ 95, 92, 90 ] }, { "_id" : 2, "grades" : [ 98, 100, 102 ] }, { "_id" : 3, "grades" : [ 95, 110, 100 ] } ] );
为了修改 grades
数组中所有大于或等于 100
的元素,使用带有 arrayFilters
选项的过滤位置操作符 $[<identifier>]
db.runCommand( { update: "students", updates: [ { q: { grades: { $gte: 100 } }, u: { $set: { "grades.$[element]" : 100 } }, arrayFilters: [ { "element": { $gte: 100 } } ], multi: true} ] } )
操作完成后,集合包含以下文档
{ "_id" : 1, "grades" : [ 95, 92, 90 ] } { "_id" : 2, "grades" : [ 98, 100, 100 ] } { "_id" : 3, "grades" : [ 95, 100, 100 ] }
更新文档数组中的特定元素
创建一个包含以下文档的集合 students2
db.students2.insertMany( [ { "_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 } ] } ] )
要修改grades
数组中所有成绩大于或等于85
的元素的mean
字段的值,请使用带有arrayFilters
的筛选位置操作符$[<identifier>]
。
db.runCommand({ update: "students2", updates: [ { q: { }, u: { $set: { "grades.$[elem].mean" : 100 } }, arrayFilters: [ { "elem.grade": { $gte: 85 } } ], multi: true } ] })
操作后,集合具有以下文档
{ "_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" : 100, "std" : 6 }, { "grade" : 87, "mean" : 100, "std" : 3 }, { "grade" : 85, "mean" : 100, "std" : 4 } ] }
为更新操作指定hint
创建以下文档的members
集合
db.members.insertMany([ { "_id" : 1, "member" : "abc123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null }, { "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }, { "_id" : 3, "member" : "lmn123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null }, { "_id" : 4, "member" : "pqr123", "status" : "D", "points" : 20, "misc1" : "Deactivated", "misc2" : null }, { "_id" : 5, "member" : "ijk123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null }, { "_id" : 6, "member" : "cde123", "status" : "A", "points" : 86, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" } ])
在集合上创建以下索引
db.members.createIndex( { status: 1 } ) db.members.createIndex( { points: 1 } )
以下更新操作明确提示使用索引{ status: 1 }
注意
如果您指定了一个不存在的索引,则操作将出错。
db.runCommand({ update: "members", updates: [ { q: { "points": { $lte: 20 }, "status": "P" }, u: { $set: { "misc1": "Need to activate" } }, hint: { status: 1 }, multi: true } ] })
更新命令返回以下结果
{ "n" : 3, "nModified" : 3, "ok" : 1 }
要查看使用的索引,在操作上运行explain
db.runCommand( { explain: { update: "members", updates: [ { q: { "points": { $lte: 20 }, "status": "P" }, u: { $set: { "misc1": "Need to activate" } }, hint: { status: 1 }, multi: true } ] }, verbosity: "queryPlanner" } )
explain
不会修改文档。
在let
选项或c
字段中使用变量
新在版本5.0.
变量可以在let选项或c字段中定义,并在updates
数组中访问。
注意
要使用变量进行结果筛选,必须在$expr
操作符内访问该变量。
创建集合cakeFlavors
db.cakeFlavors.insertMany( [ { _id: 1, flavor: "chocolate" }, { _id: 2, flavor: "strawberry" }, { _id: 3, flavor: "cherry" } ] )
以下示例在let
中定义了targetFlavor
和newFlavor
变量,并使用这些变量将蛋糕口味从樱桃改为橙子。
db.runCommand( { update: db.cakeFlavors.getName(), updates: [ { q: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } }, u: [ { $set: { flavor: "$$newFlavor" } } ] } ], let : { targetFlavor: "cherry", newFlavor: "orange" } } )
下一个示例在c
中定义了targetFlavor
和newFlavor
变量,并使用这些变量将蛋糕口味从巧克力改为香草。
db.runCommand( { update: db.cakeFlavors.getName(), updates: [ { q: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } }, u: [ { $set: { flavor: "$$newFlavor" } } ], c: { targetFlavor: "chocolate", newFlavor: "vanilla" } } ] } )
输出
返回的文档包含以下字段的子集
update.n
update
命令接受一个文档更新数组,其中一些可以是upserts。对于更新,n
是选择用于更新的文档数。对于upsert,n
是插入的文档的1
。服务器将所有更新和upserts的n
值相加,并将总和作为update.n
返回。
update.nModified
更新的文档数量。如果更新操作没有改变文档,例如将字段的值设置为当前值,
nModified
可以小于n
。注意
如果匹配的文档子集被更新,例如,当更新会导致某些文档失败模式验证时,
update
命令返回的nModified
值可能不准确。
update.writeConcernError
描述与写入关注点相关的错误的文档。
writeConcernError
文档包含以下字段update.writeConcernError.errInfo.writeConcern
用于相应操作的写关注对象。有关写关注对象字段的信息,请参阅写关注规范。
写关注对象还可以包含以下字段,指示写关注的来源
update.writeConcernError.errInfo.writeConcern.provenance
指示写关注来源的字符串值(称为写关注
provenance
)。以下表格显示了此字段的可能值及其含义来源描述clientSupplied
写关注是在应用程序中指定的。customDefault
写关注来源于自定义定义的默认值。请参阅setDefaultRWConcern
。getLastErrorDefaults
写关注来源于副本集的settings.getLastErrorDefaults
字段。implicitDefault
在所有其他写关注规范缺失的情况下,写关注来源于服务器。
除了上述特定于更新的返回字段之外,db.runCommand()
还包括其他信息
对于副本集:
optime
、electionId
、$clusterTime
和operationTime
。对于分片集群:
operationTime
和$clusterTime
。
有关这些字段的详细信息,请参阅db.runCommand 响应。
以下是一个成功执行的update
命令返回的示例文档,该命令执行了upsert操作
{ "ok" : 1, "nModified" : 0, "n" : 1, "upserted" : [ { "index" : 0, "_id" : ObjectId("52ccb2118908ccd753d65882") } ] }
以下是一个示例文档,展示了包含三个更新语句的大批量更新操作的结果,其中一条更新语句成功执行,另外两条更新语句遇到错误。
{ "ok" : 1, "nModified" : 1, "n" : 1, "writeErrors" : [ { "index" : 1, "code" : 16837, "errmsg" : "The _id field cannot be changed from {_id: 1.0} to {_id: 5.0}." }, { "index" : 2, "code" : 16837, "errmsg" : "The _id field cannot be changed from {_id: 2.0} to {_id: 6.0}." }, ] }