Docs Menu

Update Arrays in a Document

On this page

  • Overview
  • Sample Documents
  • Specifying Array Elements
  • The First Matching Array Element
  • Matching All Array Elements
  • Matching Multiple Array Elements

In this guide, you can learn how to use the following array update operators to modify an array embedded within a document:

See the MongoDB server guide on Update Operators for a complete list.

The examples in this guide use the following sample documents from the test.pizza collection. The collection contains documents that describe the customers and their pizza orders as array elements in field called items.

[{
name: "Steve Lobsters",
address: "731 Yexington Avenue",
items: [
{ type: "beverage", name: "Water", size: "17oz", },
{ type: "pizza", size: "large", toppings: ["pepperoni"], },
{ type: "pizza", size: "medium", toppings: ["mushrooms", "sausage", "green peppers"], comment: "Extra green peppers please!", },
{ type: "pizza", size: "large", toppings: ["pineapple, ham"], comment: "red pepper flakes on top", },
{ type: "calzone", fillings: ["canadian bacon", "sausage", "onion"], },
{ type: "beverage", name: "Diet Pepsi", size: "16oz", },
],
},
{
name: "Popeye",
address: "1 Sweethaven",
items: [
{ type: "pizza", size: "large", toppings: ["garlic, spinach"], },
{ type: "calzone", toppings: ["ham"], },
],
}]

You can specify which array elements to update using a positional operator. Positional operators can specify the first, all, or certain array elements to update.

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.

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. For cases in which 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.

The following code snippet shows how to update the size of the first pizza order item to "extra large" for the customer named Steve Lobsters.

const query = { name: "Steve Lobsters", "items.type": "pizza" };
const updateDocument = {
$set: { "items.$.size": "extra large" }
};
const result = await pizza.updateOne(query, updateDocument);

The query matches all documents that contain an element embedded in the items array that contain a value of pizza in the type field. The updateDocument specifies the update operation to set the first array element match in items to "extra large".

After you run the update method, your customer document for Steve Lobsters resembles the following:

{
name: "Steve Lobsters",
address: "731 Yexington Avenue",
items: [
{ type: "pizza", size: "extra large", ... },
...
]
}

Note that we included both name and items.type fields in the query in order to match the array in which we apply the $ operator. If we omit the items.type field from the query and specify the $ operator in our update, we encounter the following error:

The positional operator did not find the match needed from the query.

To perform the update on all of the array elements of each document that matches your query, use the all positional operator $[].

The following code snippet adds "fresh mozzarella" to the toppings of all of Popeye's order items.

const query = { "name": "Popeye" };
const updateDocument = {
$push: { "items.$[].toppings": "fresh mozzarella" }
};
const result = await pizza.updateOne(query, updateDocument);

After you run the update method, your customer document for Popeye resembles the following:

{
name:"Popeye",
address: "1 Sweethaven",
items: [
{ type: "pizza", ... , toppings: ["garlic", "spinach", "fresh mozzarella"], },
{ type: "calzone", ... , toppings: ["ham", "fresh mozzarella"], },
]
}

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 options.arrayFilters object.

The <identifier> term is a placeholder value you assign that represents an element of the array field name that prefixes it. This value must start with a lowercase letter and contain only alphanumeric characters.

To add a "garlic" topping to certain order items, format your update document as follows:

{ $push: { items.$[orderItem].toppings: "garlic" } }

This update document specifies the following:

  • $push: the update operator
  • items: the array in the document to update
  • orderItem: the identifier for the filtered positional operator
  • toppings: the field on the items array element to update
  • garlic: the value to push onto the toppings array

Next, add the matching criteria in your arrayFilters object in your update operation's options parameter. This object is an array of queries that specify which array elements to include in the update. To add the "garlic" topping to order items of type "pizza" and "large size", pass the following arrayFilters:

arrayFilters: [
{ orderItem.type: "pizza" },
{ orderItem.size: "large" }
]

The following snippet shows the complete update method:

const query = { name: "Steve Lobsters" };
const updateDocument = {
$push: { "items.$[orderItem].toppings": "garlic" }
};
const options = {
arrayFilters: [{
"orderItem.type": "pizza",
"orderItem.size": "large",
}]
};
const result = await pizza.updateMany(query, updateDocument, options);

After you run the method, your customer document for Steve Lobsters resembles the following:

{
name: "Steve Lobsters",
address: "731 Yexington Avenue",
items: [
{ type: "pizza", size: "large", toppings: ["pepperoni", "garlic"] },
{ type: "pizza", size: "large", toppings: ["pineapple", "ham", "garlic"], ...},
...
]
}

Suppose Steve Lobsters wants to adjust their order to add "salami" as a topping to all pizzas that have pepperoni. To perform the update, use the filtered positional operator as follows:

const query = { name: "Steve Lobsters" };
const updateDocument = {
$push: { "items.$[item].toppings": "salami" },
};
const options = {
arrayFilters: [
{
"item.type": "pizza",
"item.toppings": "pepperoni",
},
],
};
const result = await pizza.updateOne(query, updateDocument, options);

After you run the update method, your customer document for Steve Lobsters resembles the following:

{
name: "Steve Lobsters",
address: "731 Yexington Avenue",
items: [
{ type: "pizza", size: "large", toppings: ["pepperoni", "salami"], },
{ type: "pizza", size: "medium", toppings: ["mushrooms", "sausage", "green peppers"], comment: "Extra green peppers please!", },
{ type: "pizza", size: "large", toppings: ["pineapple, ham"], comment: "red pepper flakes on top", },
{ type: "calzone", fillings: ["canadian bacon", "sausage", "onion"], },
{ type: "beverage", name: "Diet Pepsi", size: "16oz", },
],
}
←  Change a DocumentInsert or Update in a Single Operation →
Give Feedback
© 2022 MongoDB, Inc.

About

  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2022 MongoDB, Inc.