MongoDB: How to update multiple array elements matching a condition

Updated: February 3, 2024 By: Guest Contributor Post a comment

Overview

Working with arrays is a common task in MongoDB, especially when dealing with documents that contain multi-value fields. There might be situations where you need to update multiple elements of an array within your documents. This tutorial will guide you through the process of updating multiple array elements that match a specific condition using MongoDB’s powerful update operators and methods.

Prerequisites:

  • Basic understanding of MongoDB.
  • MongoDB Server installed and running.
  • Access to a MongoDB client or MongoDB Atlas for executing commands.

Understanding the Data Model

For this tutorial, let’s use a collection named products, with each document representing a product that contains an array of reviews. Each review is an object with properties such as reviewer, comment, and rating.

{
    "_id": ObjectId("some-object-id"),
    "name": "Product A",
    "reviews": [
        {
            "reviewer": "John Doe",
            "comment": "Great product",
            "rating": 5
        },
        {
            "reviewer": "Jane Doe",
            "comment": "Not bad",
            "rating": 3
        }
    ]
}

Simple Update with $set

The simplest way to update multiple array elements that match a certain condition is by using the $set operator with the $[] operator. This combination allows you to update all array elements that match your specified condition. For example, if you want to increase the rating of all reviews with a rating less than 5 to 5:

db.products.updateMany(
    { "reviews.rating": { $lt: 5 } },
    { $set: { "reviews.$[elem].rating": 5 } },
    { arrayFilters: [{ "elem.rating": { $lt: 5 } }] }
)

This command increases the rating of all reviews with a rating less than 5 to 5. Note that the arrayFilters option is used to specify which elements to update.

Updating Nested Fields

When working with deeply nested array fields, you can still use the $set operator in combination with the $[] operator and array filters to target and update specific elements. For example, if your product documents also contain a list of suppliers, and each supplier has its own list of feedbacks:

{
    "_id": ObjectId("some-object-id"),
    "name": "Product B",
    "suppliers": [
        {
            "name": "Supplier 1",
            "feedbacks": [
                {
                    "comment": "Excellent service",
                    "rating": 5
                },
                {
                    "comment": "Good, but expensive",
                    "rating": 3
                }
            ]
        }
    ]
}

To update the rating of all feedbacks with a rating less than 5 to 5:

db.products.updateMany(
    { "suppliers.feedbacks.rating": { $lt: 5 } },
    { $set: { "suppliers.$[].feedbacks.$[elem].rating": 5 } },
    { arrayFilters: [{ "elem.rating": { $lt: 5 } }] }
)

This example updates the rating of all feedbacks in all suppliers with a rating less than 5 to 5. The use of $[] signifies all elements in the array should be considered, and arrayFilters pinpoint the exact elements to modify.

Utilizing $push and $addToSet for Array Modification

Aside from updating existing elements, you might want to add new elements to an array based on certain conditions. MongoDB provides the $push and $addToSet operators for this purpose. The $push operator adds an element to an array, while $addToSet adds an element only if it does not already exist in the set, ensuring uniqueness. Here’s how you could use them:

db.products.updateMany(
    {},
    { $push:  { "reviews": { "reviewer": "New Reviewer", "comment": "New comment", "rating": 4 } }}
)

This example demonstrates how to add a new review to every product. If you want to ensure the addition is unique, the $addToSet operator would be the preferred method.

Advanced Use: Combining Operators

MongoDB’s power really shines when you start combining update operators to perform complex updates. Suppose you want to both update and add elements in the same operation. You could use a combination of $set, $push, and other operators to achieve your desired outcome. Understanding and experimenting with these combinations can lead to powerful document update patterns.

Below is a code snippet demonstrating how to combine $set and $push operators in a MongoDB update operation to both update existing fields and add new elements to an array within the same document. This example assumes you have a users collection where each document contains a name, age, and a list of hobbies.

db.users.updateOne(
  { name: "John Doe" }, // Filter document by 'name'
  {
    $set: { age: 30 }, // Update the 'age' field
    $push: { hobbies: "reading" } // Add a new hobby to the 'hobbies' array
  }
);

Explaination:

  • $set Operator: Updates the value of the age field to 30. If the field does not exist, $set will add it with the specified value.
  • $push Operator: Adds a new element, "reading", to the hobbies array. If hobbies does not exist, $push creates the array with the element in it.

This operation will find the first document where the name is "John Doe", set its age to 30, and add "reading" to its list of hobbies.

If you want to push multiple values to an array and ensure no duplicates, you could combine $set, $addToSet, and $each:

db.users.updateOne(
  { name: "Jane Doe" },
  {
    $set: { age: 28 },
    $addToSet: { 
      hobbies: { $each: ["cycling", "hiking"] } // Adds multiple hobbies, avoiding duplicates
    }
  }
);

$addToSet with $each: Instead of adding a single value, you use $addToSet with $each to add multiple unique values to the hobbies array. This approach ensures that “cycling” and “hiking” are added to the hobbies array without creating duplicates.

Conclusion

Updating multiple array elements in MongoDB documents is a powerful feature that can significantly simplify and optimize data manipulation tasks. Whether it’s updating existing elements to meet new criteria or adding unique elements to arrays, MongoDB offers a variety of operators and methods to achieve complex update operations efficiently. As always, when working with database operations, especially updates, ensure you have adequate backups and understand the potential impact on your data integrity.