On this page本页内容
update
The update
command modifies documents in a collection. update
命令修改集合中的文档。A single 一个update
command can contain multiple update statements. update
命令可以包含多个update语句。The update methods provided by the MongoDB drivers use this command internally.MongoDB驱动程序提供的更新方法在内部使用此命令。
mongosh
provides the following helper methods:提供了以下帮助器方法:
Changed in version 5.0.在版本5.0中更改。
The update
command has the following syntax:update
命令具有以下语法:
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>, writeConcern: { <write concern> }, bypassDocumentValidation: <boolean>, comment: <any>, let: <document> // Added in MongoDB 5.0 } )
The command takes the following fields:该命令接受以下字段:
update | string | |
updates | array | |
ordered | boolean | true , then when an update statement fails, return without performing the remaining update statements. If false , then when an update fails, continue with the remaining update statements, if any. Defaults to true . |
writeConcern | document |
|
bypassDocumentValidation | boolean | update to bypass document validation during the operation. This lets you update documents that do not meet the validation requirements. |
comment | any |
A comment can be any valid BSON type(string, integer, object, array, etc).
|
let | document |
{ <variable_name_1>: <expression_1>, ..., <variable_name_n>: <expression_n> }
|
Each element of the updates
array is an update statement document. updates
数组的每个元素都是一个更新语句文档。Each document contains the following fields:每个文档包含以下字段:
q | document | The query that matches documents to update. Use the same query selectors as used in the |
u | document or pipeline | The modifications to apply. The value can be either:
|
c | document | Optional.
{ <variable_name_1>: <expression_1>, ..., <variable_name_n>: <expression_n> }
For a complete example using
|
upsert | boolean |
If both To avoid multiple upserts, ensure that the Defaults to |
multi | boolean | Optional. If true , updates all documents that meet the query criteria. If false , limit the update to one document that meet the query criteria. Defaults to false . |
collation | document | Optional. Specifies the collation to use for the operation. Collation allows users to specify language-specific rules for string comparison, such as rules for lettercase and accent marks. The collation option has the following syntax: collation: { locale: <string>, caseLevel: <boolean>, caseFirst: <string>, strength: <int>, numericOrdering: <boolean>, alternate: <string>, maxVariable: <string>, backwards: <boolean> } When specifying collation, the If the collation is unspecified but the collection has a default collation (see If no collation is specified for the collection or for the operations, MongoDB uses the simple binary comparison used in prior versions for string comparisons. You cannot specify multiple collations for an operation. For example, you cannot specify different collations per field, or if performing a find with a sort, you cannot use one collation for the find and another for the sort. |
arrayFilters | array |
In the update document, use the The You can include the same identifier multiple times in the update document; however, for each distinct identifier ( // INVALID [ { "x.a": { $gt: 85 } }, { "x.b": { $gt: 80 } } ] However, you can specify compound conditions on the same identifier in a single filter document, such as in the following examples: // Example 1 [ { $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] } ] // Example 2 [ { $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] } ] // Example 3 [ { "x.a": { $gt: 85 }, "x.b": { $gt: 80 } } ] For examples, see Specify |
hint | Document or string |
The option can take an index specification document or the index name string. If you specify an index that does not exist, the operation errors. For an example, see Specify
|
The command returns a document that contains the status of the operation. For Example:例如:
{ "ok" : 1, "nModified" : 0, "n" : 1, "upserted" : [ { "index" : 0, "_id" : ObjectId("52ccb2118908ccd753d65882") } ] }
For details of the output fields, see Output.
On deployments running with authorization
, the user must have access that includes the following privileges:
update
action on the specified collection(s).find
action on the specified collection(s).insert
action on the specified collection(s).The built-in role readWrite
provides the required privileges.
The update statement field u can accept a document that only contains update operator expressions. For Example:例如:
updates: [ { q: <query>, u: { $set: { status: "D" }, $inc: { quantity: 2 } }, ... }, ... ]
Then, the update
command updates only the corresponding fields in the document.
The update statement field u field can accept a replacement document, i.e. the document contains onlyfield:value
expressions. For Example:例如:
updates: [ { q: <query>, u: { status: "D", quantity: 4 }, ... }, ... ]
Then the update
command replaces the matching document with the update document. The update
command can only replace a single matching document; i.e. the multi
field cannot be true
. The update
command does not replace the _id
value.
Starting in MongoDB 4.2, the update statement field u field can accept an aggregation pipeline [ <stage1>, <stage2>, ... ]
that specifies the modifications to perform. The pipeline can consist of the following stages:
$addFields
and its alias $set
$project
and its alias $unset
$replaceRoot
and its alias $replaceWith
.Using the aggregation pipeline allows for a more expressive update statement, such as expressing conditional updates based on current field values or updating one field using the value of another field(s).
For Example:例如:
updates: [ { q: <query>, u: [ { $set: { status: "Modified", comments: [ "$misc1", "$misc2" ] } }, { $unset: [ "misc1", "misc2" ] } ], ... }, ... ]
For examples, see Update with Aggregation Pipeline.
When using the upsert: true option with the update
command, and not using a unique index on the query field(s), multiple instances of an update
operation with similar query field(s) could result in duplicate documents being inserted in certain circumstances.
Consider an example where no document with the name Andy
exists and multiple clients issue the following command at roughly the same time:
db.runCommand( { update: "people", updates: [ { q: { name: "Andy" }, u: { $inc: { score: 1 } }, multi: true, upsert: true } ] } )
If all update
operations finish the query phase before any client successfully inserts data, and there is no unique index on the name
field, each update
operation may result in an insert, creating multiple documents with name: Andy
.
To ensure that only one such document is created, and the other update
operations update this new document instead, create a unique index on the name
field. This guarantees that only one document with name: Andy
is permitted in the collection.
With this unique index in place, the multiple update
operations now exhibit the following behavior:
For each update element in the updates
array, the sum of the query and the update sizes (i.e. q
and u
) must be less than or equal to the maximum BSON document size.
The total number of update statements in the updates
array must be less than or equal to the maximum bulk size.
The update
command adds support for the bypassDocumentValidation
option, which lets you bypass document validation when inserting or updating documents in a collection with validation rules.
upsert
on a Sharded CollectionTo use update
with multi: false
on a sharded collection,
_id
field or target a single shard (such as by including the shard key).If you specify upsert: true, the filter q must include an equality match on the shard key.
However, starting in version 4.4, documents in a sharded collection can be missing the shard key fields. To target a document that is missing the shard key, you can use the null
equality match in conjunction with another filter condition (such as on the _id
field). For Example:例如:
{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key
Starting in MongoDB 4.2, when replacing a document, update
attempts to target a shard, first by using the query filter. If the operation cannot target a single shard by the query filter, it then attempts to target by the replacement document.
In earlier versions, the operation attempts to target using the replacement document.
Starting in MongoDB 4.2, you can update a document's shard key value unless the shard key field is the immutable _id
field. In MongoDB 4.2 and earlier, a document's shard key field value is immutable.
To modify the existing shard key value with update
:
mongos
. Do not issue the operation directly on the shard.multi: false
.Since a missing key value is returned as part of a null equality match, to avoid updating a null-valued key, include additional query conditions (such as on the _id
field) as appropriate.
See also upsert
on a Sharded Collection.
Starting in version 4.4, documents in a sharded collection can be missing the shard key fields. To use update
to set the document's missing shard key, you must run on a mongos
. Do not issue the operation directly on the shard.
In addition, the following requirements also apply:
Task | Requirements |
---|---|
To set to null |
|
To set to a non-null value: |
|
Since a missing key value is returned as part of a null equality match, to avoid updating a null-valued key, include additional query conditions (such as on the _id
field) as appropriate.
See also:
update
can be used inside multi-document transactions.
In most cases, multi-document transaction incurs a greater performance cost over single document writes, and the availability of multi-document transactions should not be a replacement for effective schema design. For many scenarios, the denormalized data model (embedded documents and arrays) will continue to be optimal for your data and use cases. That is, for many scenarios, modeling your data appropriately will minimize the need for multi-document transactions.
For additional transactions usage considerations (such as runtime limit and oplog size limit), see also Production Considerations.
Starting in MongoDB 4.4, you can create collections and indexes inside a multi-document transaction if the transaction is not a cross-shard write transaction.
Specifically, in MongoDB 4.4 and greater, update
with upsert: true
can be run on an existing collection or a non-existing collection. If run on a non-existing collection, the operation creates the collection.
In MongoDB 4.2 and earlier, the operation must be run on an existing collection.
Do not explicitly set the write concern for the operation if run in a transaction. To use write concern with transactions, see Transactions and Write Concern.
Use update operators to update only the specified fields of a document.
For example, create a members
collection with the following documents:
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" }, ])
The following command uses the $set
and $inc
update operators to update the status
and the points
fields of a document where the member
equals "abc123"
:
db.runCommand( { update: "members", updates: [ { q: { member: "abc123" }, u: { $set: { status: "A" }, $inc: { points: 1 } } } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
Because <update>
document does not specify the optional multi
field, the update only modifies one document, even if more than one document matches the q
match condition.
The returned document shows that the command found and updated a single document. The command returns:
{ "n" : 1, "nModified" : 1, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
See Output for details.
After the command, the collection contains the following documents:
{ "_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" }
Use update operators to update only the specified fields of a document, and include the multi
field set to true
in the update statement.
For example, a members
collection contains the following documents:
{ "_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" }
The following command uses the $set
and $inc
update operators to modify the status
and the points
fields respectively of all documents in the collection:
db.runCommand( { update: "members", updates: [ { q: { }, u: { $set: { status: "A" }, $inc: { points: 1 } }, multi: true } ], ordered: false, writeConcern: { w: "majority", wtimeout: 5000 } } )
The update modifies all documents that match the query specified in the q
field, namely the empty query which matches all documents in the collection.
The returned document shows that the command found and updated multiple documents. For a replica set, the command returns:
{ "n" : 2, "nModified" : 2, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
See Output for details.
After the command, the collection contains the following documents:
{ "_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" }
Starting in MongoDB 4.2, the update
command can use an aggregation pipeline for the update. The pipeline can consist of the following stages:
$addFields
and its alias $set
$project
and its alias $unset
$replaceRoot
and its alias $replaceWith
.Using the aggregation pipeline allows for a more expressive update statement, such as expressing conditional updates based on current field values or updating one field using the value of another field(s).
The following examples uses the aggregation pipeline to modify a field using the values of the other fields in the document.
A members
collection contains the following documents:
{ "_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" }
Assume that instead of separate misc1
and misc2
fields, you want to gather these into a new comments
field. The following update operation uses an aggregation pipeline to add the new comments
field and remove the misc1
and misc2
fields for all documents in the collection.
status
field to "Modified"
and add a new field comments
that contains the current contents of two other fields misc1
and misc2
fields.misc1
and misc2
fields.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 } } )
The returned document shows that the command found and updated multiple documents. The command returns:
{ "n" : 2, "nModified" : 2, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
See Output for details.
After the command, the collection contains the following documents:
{ "_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" ] }
The aggregation pipeline allows the update to perform conditional updates based on the current field values as well as use current field values to calculate a separate field value.
db.students.insertMany( [ { "_id" : 1, "tests" : [ 95, 92, 90 ] }, { "_id" : 2, "tests" : [ 94, 88, 90 ] }, { "_id" : 3, "tests" : [ 70, 75, 82 ] } ] );
Using an aggregation pipeline, you can update the documents with the calculated grade average and letter grade.
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
stage calculates a new field average
based on the average of the tests
field. See $avg
for more information on the $avg
aggregation operator.$set
stage calculates a new field grade
based on the average
field calculated in the previous stage. See $switch
for more information on the $switch
aggregation operator.The returned document shows that the command found and updated multiple documents. The command returns:
{ "n" : 3, "nModified" : 3, "ok" : 1, <additional fields if run on a replica set/sharded cluster> }
After the command, the collection contains the following documents:
{ "_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" }
The following example performs multiple update operations on the members
collection:
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 } } )
The returned document shows that the command modified 10
documents and inserted a document with the _id
value 5
. See Output for details.
{ "ok" : 1, "nModified" : 10, "n" : 11, "upserted" : [ { "index" : 1, "_id" : 5 } ] }
Collation allows users to specify language-specific rules for string comparison, such as rules for lettercase and accent marks.
A collection myColl
has the following documents:
{ _id: 1, category: "café", status: "A" } { _id: 2, category: "cafe", status: "a" } { _id: 3, category: "cafE", status: "a" }
The following operation includes the collation option:
db.runCommand({ update: "myColl", updates: [ { q: { category: "cafe", status: "a" }, u: { $set: { status: "Updated" } }, collation: { locale: "fr", strength: 1 } } ] })
arrayFilters
for Array Update OperationsStarting in MongoDB 3.6, when updating an array field, you can specify arrayFilters
that determine which array elements to update.
arrayFilters
CriteriaCreate a collection students
with the following documents:
db.students.insertMany( [ { "_id" : 1, "grades" : [ 95, 92, 90 ] }, { "_id" : 2, "grades" : [ 98, 100, 102 ] }, { "_id" : 3, "grades" : [ 95, 110, 100 ] } ] );
To modify all elements that are greater than or equal to 100
in the grades
array, use the filtered positional operator $[<identifier>]
with the arrayFilters
option:
db.runCommand( { update: "students", updates: [ { q: { grades: { $gte: 100 } }, u: { $set: { "grades.$[element]" : 100 } }, arrayFilters: [ { "element": { $gte: 100 } } ], multi: true} ] } )
After the operation, the collection contains the following documents:
{ "_id" : 1, "grades" : [ 95, 92, 90 ] } { "_id" : 2, "grades" : [ 98, 100, 100 ] } { "_id" : 3, "grades" : [ 95, 100, 100 ] }
Create a collection students2
with the following documents:
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 } ] } ] )
To modify the value of the mean
field for all elements in the grades
array where the grade is greater than or equal to 85
, use the filtered positional operator $[<identifier>]
with the arrayFilters
:
db.runCommand({ update: "students2", updates: [ { q: { }, u: { $set: { "grades.$[elem].mean" : 100 } }, arrayFilters: [ { "elem.grade": { $gte: 85 } } ], multi: true } ] })
After the operation, the collection has the following documents:
{ "_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
for Update OperationsNew in version 4.2.在版本4.2中新增。
Create a sample members
collection with the following documents:
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" } ])
Create the following indexes on the collection:
db.members.createIndex( { status: 1 } ) db.members.createIndex( { points: 1 } )
The following update operation explicitly hints to use the index {
status: 1 }
:
If you specify an index that does not exist, the operation errors.
db.runCommand({ update: "members", updates: [ { q: { "points": { $lte: 20 }, "status": "P" }, u: { $set: { "misc1": "Need to activate" } }, hint: { status: 1 }, multi: true } ] })
The update command returns the following:
{ "n" : 3, "nModified" : 3, "ok" : 1 }
To see the index used, run explain
on the operation:
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" } )
The explain
does not modify the documents.
let
Option or c
FieldNew in version 5.0.在版本5.0中新增。
Variables can be defined in the let option or the c field and accessed in the updates
array.
To filter results using a variable, you must access the variable within the $expr
operator.
Create a collection cakeFlavors
:
db.cakeFlavors.insertMany( [ { _id: 1, flavor: "chocolate" }, { _id: 2, flavor: "strawberry" }, { _id: 3, flavor: "cherry" } ] )
The following example defines targetFlavor
and newFlavor
variables in let
and uses the variables to change the cake flavor from cherry to orange:
db.runCommand( { update: db.cakeFlavors.getName(), updates: [ { q: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } }, u: [ { $set: { flavor: "$$newFlavor" } } ] } ], let : { targetFlavor: "cherry", newFlavor: "orange" } } )
The next example defines targetFlavor
and newFlavor
variables in c
and uses the variables to change the cake flavor from chocolate to vanilla:
db.runCommand( { update: db.cakeFlavors.getName(), updates: [ { q: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } }, u: [ { $set: { flavor: "$$newFlavor" } } ], c: { targetFlavor: "chocolate", newFlavor: "vanilla" } } ] } )
The returned document contains a subset of the following fields:
update.n
The number of documents selected for update. If the update operation results in no change to the document, e.g. $set
expression updates the value to the current value, n
can be greater than nModified
.
update.nModified
The number of documents updated. If the update operation results in no change to the document, such as setting the value of the field to its current value, nModified
can be less than n
.
update.upserted
An array of documents that contains information for each document inserted through the update with upsert: true
.
Each document contains the following information:
update.writeErrors
An array of documents that contains information regarding any error encountered during the update operation. The writeErrors
array contains an error document for each update statement that errors.
Each error document contains the following fields:
update.writeConcernError
Document that describe error related to write concern and contains the field:
update.writeConcernError.errInfo.writeConcern
New in version 4.4.在版本4.4中新增。
The write concern object used for the corresponding operation. For information on write concern object fields, see Write Concern Specification.
The write concern object may also contain the following field, indicating the source of the write concern:
update.writeConcernError.errInfo.writeConcern.provenance
A string value indicating where the write concern originated (known as write concern provenance
). The following table shows the possible values for this field and their significance:
Provenance | |
---|---|
clientSupplied | The write concern was specified in the application. |
customDefault | The write concern originated from a custom defined default value. See setDefaultRWConcern . |
getLastErrorDefaults | The write concern originated from the replica set's settings.getLastErrorDefaults field. |
implicitDefault | The write concern originated from the server in absence of all other write concern specifications. |
In addition to the aforementioned update specific return fields, the db.runCommand()
includes additional information:
optime
, electionId
, $clusterTime
, and operationTime
.operationTime
and $clusterTime
.See db.runCommand Response for details on these fields.
The following is an example document returned for a successful update
command that performed an upsert:
{ "ok" : 1, "nModified" : 0, "n" : 1, "upserted" : [ { "index" : 0, "_id" : ObjectId("52ccb2118908ccd753d65882") } ] }
The following is an example document returned for a bulk update involving three update statements, where one update statement was successful and two other update statements encountered errors:
{ "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}." }, ] }