Search code examples
mongodbmongodb-update

mongodb update multiple Array elements using db.update()


I compiled 2 update queries by referring to related stackoverflow answers, however, it doesn't seem to work, query updates all elements while only elements matching the criteria are expected to update.

Document:

[
  {
    "_id": 259,
    "members": [
      {
        "email": "test1@gmail.com",
        "added_by": "javapedia.net",
        "status": "pending"
      },
      {
        "email": "test2@gmail.com",
        "added_by": "javapedia.net",
        "status": "pending"
      },
      {
        "email": "test3@gmail.com",
        "status": "pending"
      }
    ]
  }
]

Query1: Using elemMatch operator, mongodb playground: https://mongoplayground.net/p/4cNgWJse86W

db.collection.update({
  _id: 259,
  "members": {
    "$elemMatch": {
      "email": {
        "$in": [
          "test3@gmail.com",
          "test4@gmail.com"
        ]
      }
    }
  }
},
{
  "$set": {
    "members.$[].status": "active"
  }
},
{
  "multi": true
})

Query2: using $in, mongodb playground : https://mongoplayground.net/p/tNu395B2RFx

db.collection.update({
  _id: 259,
  "members.email": {
    "$in": [
      "test3@gmail.com",
      "test4@gmail.com"
    ]
  }
},
{
  "$set": {
    "members.$[].status": "active"
  }
},
{
  "multi": true
})

Expected result: only one element with test3@gmail.com status should be updated to active.

Actual result: both queries update all records.


Solution

  • Is this what you're looking for?

    db.collection.update({
      _id: 259,  
    },
    {
      "$set": {
        "members.$[el].status": "active"
      }
    },
    {
      arrayFilters: [
        {
          "el.email": {
            $in: [
              "test3@gmail.com",
              "test4@gmail.com"
            ]
          }
        }
      ]
    })
    
    • You can put the initial conditions back if needed, I just keep this short (and to me they make no sense).

    • multi:true isn't needed for one document

    • Maybe better semantically to use updateOne()