Hướng dẫn update field mongodb

Docs HomeMongoDB Manual

Show

➤ Use the Select your language drop-down menu in the upper-right to set the language of the following examples.


Note

Starting 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:

  • The _id field is always the first field in the document.

  • Updates that include renaming of field names may result in the reordering of fields in the document.

With write concerns, you can specify the level of acknowledgement requested from MongoDB for write operations. For details, see Write Concern.

Docs HomeMongoDB Manual

$

The positional $ operator identifies 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>].

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:

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:

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

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

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