Docs Home → MongoDB Manual
➤ Use the Select your language drop-down menu in the upper-right to set the language of the following examples.
NoteStarting in MongoDB 4.2, MongoDB can accept an aggregation pipeline to
specify the modifications to make instead of an update document. See the method reference page for details. All write operations in MongoDB are atomic on the level of a single document. For more information on MongoDB and atomicity, see Atomicity and Transactions. Once set, you cannot update the value of the _id field nor
can you replace an existing document with a replacement document that has a different _id field value. For write operations, MongoDB preserves the order of the document fields except for the following cases: With write concerns, you can specify the level of acknowledgement requested from MongoDB for write operations. For details, see Write Concern. Docs Home → MongoDB Manual $ The
positional $ operator identifies an element in an array to update without explicitly specifying the position of the element in the array. NoteDisambiguationTo project, or return, an array element from a read operation, see the
$ projection operator instead. To update all elements in an array, see the all positional operator $[] instead. To update all elements that match an array filter condition or conditions, see the
filtered positional operator instead $[<identifier>] .
The positional $ operator has the form: When used with update operations, e.g.
db.collection.updateOne() and db.collection.findAndModify() , the positional $
operator acts as a placeholder for the first element that matches the query document , and the array field must appear as part of the query
document .
For example: db.collection.updateOne( | { <array>: value ... }, | { <update operator>: { "<array>.$" : value } } | ) |
Starting in MongoDB 5.0, update operators process document fields with string-based names in lexicographic order. Fields with numeric names are processed in numeric order. See
Update Operators Behavior for details. Do not use the positional operator $ with upsert operations
because inserts will use the $ as a field name in the inserted document. The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the
$ placeholder is a single value When used with the $unset operator, the positional
$ operator does not remove the matching element from the array but rather sets it to null . If the query matches the array using a negation operator, such as $ne ,
$not , or $nin , then you cannot use the positional operator to update values from this array. However, if the negated portion of the query is inside of an
$elemMatch expression, then you can use the positional operator to update this field. The positional $ update operator behaves ambiguously when filtering on multiple array fields. When the
server executes an update method, it first runs a query to determine which documents you want to update. If the update filters documents on multiple array fields, the subsequent call to the positional $ update operator doesn't always update the required position in the array. For more information, see the
example. Create a collection students with the following documents: db.students.insertMany( [ | { "_id" : 1, "grades" : [ 85, 80, 80 ] }, | { "_id" : 2, "grades" : [ 88, 90, 92 ] }, | { "_id" : 3, "grades" : [ 85, 100, 90 ] } | ] ) |
To update the first element whose value is 80 to 82 in the in the grades array, use the positional
$ operator if you do not know the position of the element in the array: ImportantYou must include the array field as part of the query document. db.students.updateOne( | { _id: 1, grades: 80 }, | { $set: { "grades.$" : 82 } } | ) |
The positional $ operator acts as a placeholder for the first match of the update query document. After the operation, the students collection contains the following documents: { "_id" : 1, "grades" : [ 85, 82, 80 ] } | { "_id" : 2, "grades" : [ 88, 90, 92 ] } | { "_id" : 3, "grades" : [ 85, 100, 90 ] } |
The positional
$ operator facilitates updates to arrays that contain embedded documents. Use the positional $ operator to access the fields in the embedded documents with the
dot notation on the $ operator. db.collection.updateOne( | { <query selector> }, | { <update operator>: { "array.$.field" : value } } | ) |
Consider the following document in the students collection whose grades element value is an array of embedded documents: { | _id: 4, | grades: [ | { grade: 80, mean: 75, std: 8 }, | { grade: 85, mean: 90, std: 5 }, | { grade: 85, mean: 85, std: 8 } | ] | } |
Use the positional
$ operator to update the std field of the first array element that matches the grade equal to 85 condition: ImportantYou must include the array field as part of the query document. db.students.updateOne( | { _id: 4, "grades.grade": 85 }, | { $set: { "grades.$.std" : 6 } } | ) |
After the operation, the document has the following updated values:
{ | "_id" : 4, | "grades" : [ | { "grade" : 80, "mean" : 75, "std" : 8 }, | { "grade" : 85, "mean" : 90, "std" : 6 }, | { "grade" : 85, "mean" : 85, "std" : 8 } | ] | } |
The $ operator can update the first array element that matches multiple query criteria specified with the $elemMatch operator. Consider the following document in the students
collection whose grades field value is an array of embedded documents: { | _id: 5, | grades: [ | { grade: 80, mean: 75, std: 8 }, | { grade: 85, mean: 90, std: 5 }, | { grade: 90, mean: 85, std: 3 } | ] | } |
In the example below, the $ operator updates the value of the std field in the first embedded document that has grade field with a value less than or equal to 90 and a mean field with a value greater than 80 : db.students.updateOne( | { | _id: 5, | grades: { $elemMatch: { grade: { $lte: 90 }, mean: { $gt: 80 } } } | }, | { $set: { "grades.$.std" : 6 } } | ) |
This
operation updates the first embedded document that matches the criteria, namely the second embedded document in the array: { | _id: 5, | grades: [ | { grade: 80, mean: 75, std: 8 }, | { grade: 85, mean: 90, std: 6 }, | { grade: 90, mean: 85, std: 3 } | ] | } |
The positional $ update operator behaves ambiguously when the query has multiple array fields to filter documents in the collection. Consider a document in the students_deans_list collection,
which holds arrays of student information: db.students_deans_list.insertMany( [ | { | _id: 8, | activity_ids: [ 1, 2 ], | grades: [ 90, 95 ], | deans_list: [ 2021, 2020 ] | } | ] ) |
In the following example, the user attempts to modify the deans_list field, filtering documents using the activity_ids , deans_list , and grades fields, and updating the 2021 value in the deans_list field to 2022: db.students_deans_list.updateOne( | { activity_ids: 1, grades: 95, deans_list: 2021 }, | { $set: { "deans_list.$": 2022 } } | ) |
When the server executes the updateOne method above, it filters the available documents using values in the supplied array fields. Although the deans_list field is used in the filter, it is not the field used
by the positional $ update operator to determine which position in the array to update: db.students_deans_list.find( { _id: 8 } )
Example output: { | _id: 8, | activity_ids: [ 1, 2 ], | grades: [ 90, 95 ], | deans_list: [ 2021, 2022 ] | } |
The updateOne method matched the deans_list field on 2021, but the positional
$ update operator instead changed the 2020 value to 2022. To avoid unexpected results when matching on multiple arrays, instead use the filtered positional operator $[<identifier>] .
Tip |