Update Arrays in a Document
On this page
Overview
In this guide, you can learn how to use the following array update operators to modify an array embedded within a document:
Filtered Positional Operator:
$[<identifier>]
For a list of array update operators, see Update Operators in the Server Manual documentation.
Specifying Array Elements
Positional operators specify which array elements to update. You can use these operators to apply updates to the first element, all elements, or certain elements of an array that match a criteria.
To specify elements in an array with positional operators, use dot notation. Dot notation is a property access syntax for navigating BSON objects. To learn more, see dot notation.
The First Matching Array Element
To update the first array element of each document that matches your
query, use the positional operator $
.
The positional operator $
references the array matched by the query.
You cannot use this operator to reference a nested array. If you want to
access a nested array, use the filtered positional operator.
Important
Do not use the $
operator in an upsert
call because the
driver treats $
as a field name in the insert document.
Example
This example uses the following sample document to show how to update the first matching array element:
{ _id: ..., entries: [ { x: false, y: 1 }, { x: "hello", y: 100 }, { x: "goodbye", y: 1000 } ] }
The following code shows how to increment a value in the first array element that matches a query.
The query matches elements in the entries
array where the value of
x
is a string
type. The update increases the y
value by
33
in the first matching element.
// Query for all elements in entries array where the value of x is a string const query = { "entries.x": { $type : "string" } }; // On first matched element, increase value of y by 33 const updateDocument = { $inc: { "entries.$.y": 33 } }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument);
After you run the update operation, the document resembles the following:
{ _id: ..., entries: [ { x: false, y: 1 }, { x: "hello", y: 133 }, { x: "goodbye", y: 1000 } ] }
The example includes the entries.x
field in the
query to match the array that the $
operator applies an update to. If you
omit the entries.x
field from the query while using the
$
operator in an update, the driver is unable to identify the
matching array and raises the following error:
MongoServerError: The positional operator did not find the match needed from the query.
Matching All Array Elements
To perform the update on all array elements of each document that
matches your query, use the all positional operator $[]
.
Example
This example uses the following sample documents, which describe phone call logs, to show how to update all matching array elements:
{ _id: ..., date: "5/15/2023", calls: [ { time: "10:08 AM", caller: "Mom", duration: 67 }, { time: "04:11 PM", caller: "Dad", duration: 121 }, { time: "06:36 PM", caller: "Grandpa", duration: 13 } ] }, { _id: ..., date: "5/16/2023", calls: [ { time: "11:47 AM", caller: "Mom", duration: 4 }, ] }
The following code shows how to remove the duration
field from
all calls
array entries in the document whose date
is
"5/15/2023"
:
// Query for all documents where date is the string "5/15/2023" const query = { date: "5/15/2023" }; // For each matched document, remove duration field from all entries in calls array const updateDocument = { $unset: { "calls.$[].duration": "" } }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument);
After you run the update operation, the documents resemble the following:
{ _id: ..., date: "5/15/2023", calls: [ { time: "10:08 AM", caller: "Mom" }, { time: "04:11 PM", caller: "Dad" }, { time: "06:36 PM", caller: "Grandpa" } ] }, { _id: ..., date: "5/16/2023", calls: [ { time: "11:47 AM", caller: "Mom", duration: 4 }, ] }
Matching Multiple Array Elements
To perform an update on all embedded array elements of each document
that matches your query, use the filtered positional operator
$[<identifier>]
.
The filtered positional operator $[<identifier>]
specifies the
matching array elements in the update document. To identify which array
elements to match, pair this operator with <identifier>
in an
arrayFilters
object.
The <identifier>
placeholder represents an element of the array
field. You must select a value for <identifier>
that starts with a
lowercase letter and contains only alphanumeric characters.
Usage
You can use a filtered positional operator in an update operation. An update operation takes a query, an update document, and optionally, an options object as its parameters.
The following steps describe how to use a filtered positional operator in an update operation:
Format your update document as follows:
{ $<operator>: { "<array>.$[<identifier>].<arrayField>": <updateParameter> } } This update document contains the following placeholders:
$<operator>
: The array update operator<array>
: The array in the document to update<identifier>
: The identifier for the filtered positional operator<arrayField>
: The field in the<array>
array element to update<updateParameter>
: The value that describes the update
Add the matching criteria in the
arrayFilters
object. This object is an array of queries that specify which array elements to include in the update. Set this object in anoptions
parameter:arrayFilters: [ { "<identifier>.<arrayField1>": <updateParameter1> }, { "<identifier>.<arrayField2>": <updateParameter2> }, ... ] Pass the query, the update document, and options to an update method. The following sample code shows how to call the
updateOne()
method with these parameters:await myColl.updateOne(query, updateDocument, options);
Example
This example uses the following sample documents, which describe shopping lists for specific recipes, to show how to update certain matching array elements:
{ _id: ..., date: "11/12/2023", items: [ { item: "Scallions", quantity: 3, recipe: "Fried rice" }, { item: "Mangos", quantity: 4, recipe: "Salsa" }, { item: "Pork shoulder", quantity: 1, recipe: "Fried rice" }, { item: "Sesame oil", quantity: 1, recipe: "Fried rice" } ] }, { _id: ..., date: "11/20/2023", items: [ { item: "Coffee beans", quantity: 1, recipe: "Coffee" } ] }
Suppose you want to increase the quantity of items you purchase for a
recipe on your "11/12/2023"
grocery trip. You want to double the quantity if
the item meets all the following criteria:
The item is for the
"Fried rice"
recipe.The item name does not include the word
"oil"
.
To double the quantity
value in the matching array
entries, use the filtered positional operator as shown in the following
code:
// Query for all documents where date is the string "11/12/2023" const query = { date: "11/12/2023" }; // For each matched document, change the quantity of items to 2 const updateDocument = { $mul: { "items.$[i].quantity": 2 } }; // Update only non-oil items used for fried rice const options = { arrayFilters: [ { "i.recipe": "Fried rice", "i.item": { $not: { $regex: "oil" } }, } ] }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument, options);
The update multiplied the quantity
value by 2
for
items that matched the criteria. The item "Sesame oil"
did not match
the criteria in the arrayFilters
object and therefore was excluded
from the update. The following documents reflect these changes:
{ _id: ..., date: "11/12/2023", items: [ { item: "Scallions", quantity: 6, recipe: "Fried rice" }, { item: "Mangos", quantity: 4, recipe: "Salsa" }, { item: "Pork shoulder", quantity: 2, recipe: "Fried rice" }, { item: "Sesame oil", quantity: 1, recipe: "Fried rice" } ] }, { _id: ..., date: "11/20/2023", items: [ { item: "Coffee beans", quantity: 1, recipe: "Coffee" } ] }