Definition
$Use the positional
$operator to identify an element in an array to update without explicitly specifying the position of the element in the array.Note
Disambiguation
To 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>].
Compatibility
You can use the positional $ operator for deployments hosted in the following
environments:
MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud
MongoDB Enterprise: The subscription-based, self-managed version of MongoDB
MongoDB Community: The source-available, free-to-use, and self-managed version of MongoDB
Syntax
The positional $ operator has the form:
{ "<array>.$" : value }
When you use update operations, such as
db.collection.updateOne() and
db.collection.findAndModify(), both of the following conditions
must be true:
The positional
$operator acts as a placeholder for the first element that matches thequery document.The
arrayfield must appear as part of thequery document.
For example:
db.collection.updateOne( { <array>: value ... }, { <update operator>: { "<array>.$" : value } } )
Behavior
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.
upsert
Do not use the $ operator in upsert operations. If the
update query does not match any existing documents, the upsert fails
because the $ operator requires a matching array element.
Nested Arrays
You cannot use the positional $ operator for queries that
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.
Unsets
When you use the positional $ operator with the
$unset operator, the positional operator does not remove
the matching element from the array. Instead, it sets the element
to null.
Negations
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.
You can use the positional operator if the negated portion of the
query is inside an $elemMatch expression.
Multiple Array Matches
The positional $ update operator behaves ambiguously when you filter
on multiple array fields.
When the server executes an update method, it first runs a query to determine
which documents to update. If the update filters documents on multiple
array fields, the positional $ update operator might not update the
correct position in the array.
For more information, see the example.
Examples
Update Values in an Array
Create the students collection 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:
Important
You 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:
db.students.insertMany ( [ { _id : 1, "grades" : [ 85, 82, 80 ] }, { _id : 2, "grades" : [ 88, 90, 92 ] }, { _id : 3, "grades" : [ 85, 100, 90 ] } ] )
Update Documents in an Array
The positional $ operator allows updates to arrays
that have embedded documents. Use the positional $
operator to access fields in embedded documents. Use
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:
db.students.insertOne( [ { _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:
Important
You 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 } ] }
Update Embedded Documents Using Multiple Field Matches
Use the $ operator to 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:
db.students.insertOne( [ { _id: 5, grades: [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 90, mean: 85, std: 3 } ] } ] )
In the following example, the $ operator updates the value of the
std field in the first embedded document that has a 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 } ] }
Update with Multiple Array Matches
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.
The example filters documents using the activity_ids, deans_list, and
grades fields, and updates 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 preceding updateOne method, 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, use the
filtered positional operator $[<identifier>].
Learn More
For examples that use the $ operator to update arrays, see
Update Array Elements in a Document with MQL Positional Operators.