Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Mohamed-Code-309/b7243dbb3fe0b8b945bd29e0e37ee94e to your computer and use it in GitHub Desktop.
Save Mohamed-Code-309/b7243dbb3fe0b8b945bd29e0e37ee94e to your computer and use it in GitHub Desktop.

How To Update Array Elements in MongoDB Documents [...]

  1. $set
  2. $(update)
  3. $[]
  4. $[<identifier>] with arrayFilter option

Definition:

The $set operator in general is used to set the value of any field in a document to a new value.

When used to update an array field, $set can be used to update the entire array, or to update a specific element in the array.

Syntax:

{ $set: { <field1>: <value1>, ... } }
//or
{ $set: { <field1.index>: <value1>, ... } }

Examples:

Consider the following document in a collection named products:

   {
     "_id": 100,
     "quantity": 250,
     "instock": true,
     "reorder": false,
     "details": { "model": "14QQ", "make": "Clothes Corp" },
     "tags": [ "apparel", "clothing" ],
     "ratings": [ { "by": "Customer007", "rating": 4 } ]
   }

(1) To update the enrite tags field of the document :

db.products.updateOne(
   { _id: 100 },
   {
      $set: 
      {
        tags: ["accessories", "fashion", "clothing"]
      }
   }
)

The previous update operation replaces the entire tags array with a new array containing the values "accessories", "fashion", and "clothing".

After running this update operation, the tags array in the document will be updated to:

"tags": [ "accessories", "fashion", "clothing" ]

(2) To update one specific item in the tags field array :

db.products.updateOne(
   { _id: 100 },
   {
      $set: 
      {
        "tags.1": "style"      
      }
   }
)

The previous query uses dot notation to access the second element in the tags array (index position 1) and sets its value to "style".

After running this update operation, the tags array in the document will be updated to:

"tags": [ "accessories", "style", "clothing" ]

Note that using $set to update an entire array will replace the existing array with the new one, while using $set with dot notation to access a specific element in the array will modify only that element.

Table of contents ☝️


Definition:

The $ positional operator allows you to update specific elements of an array within a document without knowing it's exact location in the array.

When used in an update operation, it identifies the index of the matching element in the array and updates only that element.

Syntax:

{ "<array>.$" : value }

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 $set|$inc>: { "<array>.$" : value } }
)

Examples:

(1) Consider the following documents in a collection named students:

[
   { "_id" : 1, "grades" : [ 90, 80, 80 ] },
   { "_id" : 2, "grades" : [ 88, 90, 92 ] },
   { "_id" : 3, "grades" : [ 80, 100, 90 ] }
]

To update the first occurrence of the value 80 in the grades array with the value 82:

db.students.updateOne(
   { _id: 1, grades: 80 },
   { $set: { "grades.$" : 82 } }
)

The resulting documents will look like this:

[   
    { "_id" : 1, "grades" : [ 90, 82, 80 ] }, //changed
    { "_id" : 2, "grades" : [ 88, 90, 92 ] },
    { "_id" : 3, "grades" : [ 80, 100, 90 ] }
]

If you use updateMany() instead of updateOne(), it will update all documents that match the filter condition, the $ operator will update the first matching element in each matched document's array.

The query:

db.students.updateMany(
   { grades: 80 },
   { $set: { "grades.$" : 82 } }
)

The resulting documents will look like this:

[   
    { "_id" : 1, "grades" : [ 85, 82, 80 ] }, //changed
    { "_id" : 2, "grades" : [ 88, 90, 92 ] },
    { "_id" : 3, "grades" : [ 82, 100, 90 ] } //changed
]

(2) Consider the following document in a collection named products:

   {
     "_id": 100,
     "quantity": 250,
     "instock": true,
     "details": { "model": "14QQ", "make": "Clothes Corp" },
     "ratings": 
     [ 
        { "customer": "007", "rating": 4 },
        { "customer": "003", "rating": 2 }, 
        { "customer": "001", "rating": 3 }
     ]
   }

The field ratings is an array of objetcs contaning rating for each customer who bought the product.

To update the rating value of a specific customer :

db.products.updateOne(
   { _id: 100, "ratings.customer": "003" },
   { $set: { "ratings.$.rating" : 5 } }
)

The resulting ratings array field will look like this:

"ratings": [ 
    { "customer": "007", "rating": 4 },
    { "customer": "003", "rating": 5 }, //changed
    { "customer": "001", "rating": 3 }
]

Note that the operator can only be used in the update object of an update operation, and not in the query object. In the query object, dot notation is used to access nested fields in the document.

Also remember that the array field need to be updated must appear as part of the query object.

Table of contents ☝️


Definition:

The $[] operator is called the all positional operator and is used to update all elements of an array within a document.

Syntax:

{ "<array>.$[]" : value }

unlike the $ positional operator, it can be used without putting the array in the query part, in other words, we can update the whole array.

Examples:

(1) Consider the following document in a collection named students:

{ 
    "_id" : 3, 
    "name": "Fady",
    "grades" : [ 88, 90, 88, 85 ] 
}

If you want to update the grades for a particular student with a certain name, you can use the $[] operator in the update operation like this:

db.students.update(
  { name: "Fady" },
  { $set: { "grades.$[]": 90 } } 
);

After running this update operation, the updated document will look like:

{ 
  "_id" : 3, 
  "name": "Fady",
  "grades" : [ 90, 90, 90, 90 ] 
}

(2) Suppose you have the following documents in the students collection:

[
   {
      "_id": 1,
      "name": "Omnia",
      "exams": [ 
         { "subject": "math", "score": 80 },
         { "subject": "english", "score": 90 },
         { "subject": "history", "score": 85 }
      ]
   },
   {
      "_id": 2,
      "name": "Ahmed",
      "exams": [
         { "subject": "math", "score": 75 },
         { "subject": "english", "score": 80 },
         { "subject": "history", "score": 90 }
      ]
   }
]

If you want to update the score property for all objects in the exams array where the subject property is "math", you can use the following query:

db.students.updateMany(
   { "exams.subject": "math" },
   { $set: { "exams.$[].score": 90 } }
)

After running this update operation, the updated documents will look like:

[
   {
      "_id": 1,
      "name": "Omnia",
      "exams": [ 
         { "subject": "math", "score": 90 },
         { "subject": "english", "score": 90 },
         { "subject": "history", "score": 85 }
      ]
   },
   {
      "_id": 2,
      "name": "Ahmed",
      "exams": [
         { "subject": "math", "score": 90 },
         { "subject": "english", "score": 80 },
         { "subject": "history", "score": 90 }
      ]
   }
]

Table of contents ☝️


Definition:

The arrayFilters option is used to filter elements of an array field that match specific conditions.

This option allows you to specify a set of conditions to filter the elements of an array, and then update only the matching elements.

Syntax:

{ <update operator $set|$inc>: { "<array>.$[<identifier>]" : value } },
{ arrayFilters: [ { <identifier>: <condition> } ] }

the identifier keyword is used to specify a placeholder for the matching element within the array that should be updated, and the arrayFilters option is used to match the elements in the array that should be updated based on the identifier value and a corresponding condition.

The identifier keyword can be any word that is a valid JavaScript identifier. In other words, the identifier can consist of letters, digits and underscores. However, the identifier cannot start with a digit.

It is recommended to use descriptive and meaningful identifier to make the code more readable and understandable.

Examples:

(1) suppose you have a collection called users with the following document:

{
  "_id": 1,
  "name": "Omnia",
  "favorites": [ "pizza", "hiking", "coding" ]
}

If you want to update the "hiking" value to "swimming" in the favorites array, you can use the arrayFilters option as follows:

db.users.updateOne(
  { _id: 1 },
  { $set: { "favorites.$[element]": "swimming" } },
  { arrayFilters: [ { "element": "hiking" } ] }
)

After running the previous update operation, the favorites array in the document will look like:

[ "pizza", "swimming", "coding" ]

(2) Suppose we have a collection called students with the following documents:

[
   { "_id" : 1, "grades" : [ 1, 5, 17 ] }
   { "_id" : 2, "grades" : [ 8, 17, 18 ] }
   { "_id" : 3, "grades" : [ 15, 11, 8 ] }
]

To updates all documents in the students collection by setting any value in the grades array that is greater than or equal to 10 to 10:

db.students.updateMany(
   {},
   { $set: { "grades.$[grade]" : 10 } },
   { arrayFilters: [ { "grade": { $gte: 10 } } ] }
)

After running this update operation, the documents in the collection will look like:

[
   { "_id" : 1, "grades" : [ 1, 5, 10 ] }
   { "_id" : 2, "grades" : [ 8, 10, 10 ] }
   { "_id" : 3, "grades" : [ 10, 10, 8 ] }
]

(3) Suppose you have a document in a collection called employees that has an array field called skills:

{
  "_id": 1,
  "name": "Mohamed",
  "skills": [
    { "name": "programming", "level": "expert" },
    { "name": "design", "level": "intermediate" },
    { "name": "marketing", "level": "beginner" }
  ]
}

If you want to update the level of the skill with name equal to "programming" from "expert" value to "advanced" value in the skills array, you can use the arrayFilters option as follows:

db.employees.updateOne(
  { _id: 1 },
  { $set: { "skills.$[skill].level": "advanced" } },
  { arrayFilters: [ { "skill.name": "programming" } ] }
)

After running this update operation, the skills array in the document will look like:

[
   { "name": "programming", "level": "advanced" },
   { "name": "design", "level": "intermediate" },
   { "name": "marketing", "level": "beginner" }
]

Table of contents ☝️


Related Content:

✔️ How To Query Array Fields in MongoDB Documents

✔️ How To Add and Remove Array Elements in MongoDB Documents


Links:

🕴️ Linkedin: Dragon Slayer 🐲
📝 Articles: All Articles written by D.S

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment