Navigation

update

Definition

update

The update command modifies documents in a collection. A single update command can contain multiple update statements. The update methods provided by the MongoDB drivers use this command internally.

The mongo shell provides the following helper methods:

Syntax

Changed in version 4.2.

The update command has the following syntax:

db.runCommand(
   {
      update: <collection>,
      updates: [
         {
           q: <query>,
           u: <document or pipeline>,      // Changed in MongoDB 4.2,
           upsert: <boolean>,
           multi: <boolean>,
           collation: <document>,
           arrayFilters: <array>,
           hint: <document|string>        // Available starting in MongoDB 4.2
         },
         ...
      ],
      ordered: <boolean>,
      writeConcern: { <write concern> },
      bypassDocumentValidation: <boolean>
   }
)

Command Fields

The command takes the following fields:

Field Type Description
update string The name of the target collection.
updates array An array of one or more update statements to perform on the named collection. For details of the update statements, see Update Statements.
ordered boolean Optional. If 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

Optional. A document expressing the write concern of the update command. Omit to use the default write concern.

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.

bypassDocumentValidation boolean

Optional. Enables update to bypass document validation during the operation. This lets you update documents that do not meet the validation requirements.

New in version 3.2.

Update Statements

Each element of the updates array is an update statement document. Each document contains the following fields:

Field Type Description
q document

The query that matches documents to update. Use the same query selectors as used in the find() method.

u document or pipeline

The modifications to apply.

The value can be either:

For details, see Behavior.

upsert boolean

Optional. If true, perform an insert if no documents match the query. If both upsert and multi are true and no documents match the query, the update operation inserts only a single document.

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 locale field is mandatory; all other collation fields are optional. For descriptions of the fields, see Collation Document.

If the collation is unspecified but the collection has a default collation (see db.createCollection()), the operation uses the collation specified for the collection.

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.

New in version 3.4.

arrayFilters array

Optional. An array of filter documents that determines which array elements to modify for an update operation on an array field.

In the update document, use the $[<identifier>] filtered positional operator to define an identifier, which you then reference in the array filter documents. You cannot have an array filter document for an identifier if the identifier is not included in the update document.

Note

The <identifier> must begin with a lowercase letter and contain only alphanumeric characters.

You can include the same identifier multiple times in the update document; however, for each distinct identifier ($[identifier]) in the update document, you must specify exactly one corresponding array filter document. That is, you cannot specify multiple array filter documents for the same identifier. For example, if the update statement includes the identifier x (possibly multiple times), you cannot specify the following for arrayFilters that includes 2 separate filter documents for x:

[
  { "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:

[
  { $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]

[
  { $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]

[
  { "x.a": { $gt: 85 }, "x.b": { $gt: 80 } }
]

For examples, see Specify arrayFilters for Array Update Operations.

New in version 3.6.

hint Document or string

Optional. A document or string that specifies the index to use to support the query predicate.

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 hint for Update Operations.

New in version 4.2.

Returns

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.

Access Control

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.

Behavior

Update with an Update Operator Expressions Document

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.

Update with a Replacement Document

The update statement field u field can accept a replacement document, i.e. the document contains only field: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.

Update with an Aggregation Pipeline

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:

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" ] }
      ],
      ...
   },
   ...
]

Note

The $set and $unset used in the pipeline refers to the aggregation stages $set and $unset respectively, and not the update operators $set and $unset.

For examples, see Update with Aggregation Pipeline.

Limits

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.

Document Validation

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.

Sharded Collections

To use update with multi: false on a sharded collection,

  • If you do not specify upsert: true, you must include an equality match on the _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.

Shard Key Modification

Starting in MongoDB 4.2, you can update a document’s shard key value unless the shard key field is the immutable _id field. For details on updating the shard key, see Change a Document’s Shard Key Value.

Before MongoDB 4.2, a document’s shard key field value is immutable.

To use update to update the shard key:

  • You must specify multi: false.
  • You must run on a mongos either in a transaction or as a retryable write. Do not issue the operation directly on the shard.
  • You must include an equality condition on the full shard key in the query filter. For example, if a collection messages uses { country : 1, userid : 1 } as the shard key, to update the shard key for a document, you must include country: <value>, userid: <value> in the query filter. You can include additional fields in the query as appropriate.

Replace Document

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.

Transactions

update can be used inside multi-document transactions.

If the operation results in an upsert, the collection must already exist.

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.

Important

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.

Examples

Update Specific Fields of One Document

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" }

Update Specific Fields of Multiple Documents

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" }

Update with Aggregation Pipeline

Starting in MongoDB 4.2, the update command can use an aggregation pipeline for the update. The pipeline can consist of the following stages:

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).

Example 1

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.

  • First, set the status field to "Modified" and add a new field comments that contains the current contents of two other fields misc1 and misc2 fields.
  • Second, remove the 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 }
   }
)

Note

The $set and $unset used in the pipeline refers to the aggregation stages $set and $unset respectively, and not the update operators $set and $unset.

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" ] }

Example 2

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.insert([
   { "_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 }
   }
)

Note

The $set used in the pipeline refers to the aggregation stage $set, and not the update operators $set.

First Stage
The $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.
Second Stage
The $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" }

Bulk Update

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
      }
   ]
}

Specify Collation

New in version 3.4.

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 } }
   ]
})

Specify arrayFilters for Array Update Operations

New in version 3.6.

Starting in MongoDB 3.6, when updating an array field, you can specify arrayFilters that determine which array elements to update.

Update Elements Match arrayFilters Criteria

Create a collection students with the following documents:

db.students.insert([
   { "_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 ] }

Update Specific Elements of an Array of Documents

Create a collection students2 with the following documents:

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 }
      ]
   }
]);

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 }
   ]
}

Specify hint for Update Operations

New in version 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 }:

Note

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.

Output

The returned document contains a subset of the following fields:

update.ok

The status of the command.

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.upserted.index

An integer that identifies the update with upsert:true statement in the updates array, which uses a zero-based index.

update.upserted._id

The _id value of the added document.

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.writeErrors.index

An integer that identifies the update statement in the updates array, which uses a zero-based index.

update.writeErrors.code

An integer value identifying the error.

update.writeErrors.errmsg

A description of the error.

update.writeConcernError

Document that describe error related to write concern and contains the field:

update.writeConcernError.code

An integer value identifying the cause of the write concern error.

update.writeConcernError.errmsg

A description of the cause of the write concern error.

In addition to the aforementioned update specific return fields, the db.runCommand() includes additional information:

  • for replica sets: optime, electionId, $clusterTime, and operationTime.
  • for sharded clusters: 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}."
      },
   ]
}