Home > Mobile >  Mongodb: Push element in multiple nested array with condition
Mongodb: Push element in multiple nested array with condition

Time:12-06

How can I push value into multiple nested array with specific conditions?
I have a document like this

[
  {
    "_id": "class_a",
    "students": [
      {
        "_id": "1a",
        "name": "John",
        "grades": []
      },
      {
        "_id": "1b",
        "name": "Katie",
        "grades": []
      },
      {
        "_id": "1c",
        "name": "Andy",
        "grades": []
      },
      
    ]
  }
]

Query to insert into nested array. (Not sure what is missing here)

db.collection.update({
  "_id": "class_a",
  "students": {
    $elemMatch: {
      "_id": {
        "$in": [
          "1a",
          "1b"
        ]
      }
    }
  }
},
{
  $push: {
    "students.$.grades": "A "
  }
})

Got the following result. But I was expecting both John and Katie have A in grades

[
  {
    "_id": "class_a",
    "students": [
      {
        "_id": "1a",
        "grades": ["A "],
        "name": "John"
      },
      {
        "_id": "1b",
        "grades": [],
        "name": "Katie"
      },
      {
        "_id": "1c",
        "grades": [],
        "name": "Andy"
      }
    ]
  }
]

Expected result

[
  {
    "_id": "class_a",
    "students": [
      {
        "_id": "1a",
        "grades": ["A "],
        "name": "John"
      },
      {
        "_id": "1b",
        "grades": ["A "],
        "name": "Katie"
      },
      {
        "_id": "1c",
        "grades": [],
        "name": "Andy"
      }
    ]
  }
]

Mongo playground to test the code

CodePudding user response:

You can use $[<identifier>] to update only the items that match a condition. Your first {} is to find the relevant documents, while the arrayFilters is to find the relevant items inside the document nested array:

db.collection.update(
  {_id: "class_a", students: {$elemMatch: {_id: {$in: ["1a", "1b"]}}}},
  {$push: {"students.$[item].grades": "A "}},
  {arrayFilters: [{"item._id": {$in: ["1a", "1b"]}}], upsert: true}
)

See how it works on the playground example

CodePudding user response:

You should really use arrayFilters for these otherwse it'll only match the first entity. You don't need to use $elemMatch at all.

Playground - https://mongoplayground.net/p/_7y89KB83Ho

db.collection.update({
  "_id": "class_a"
},
{
  $push: {
    "students.$[students].grades": "A "
  }
},
{
  "arrayFilters": [
    {
      "students._id": {
        "$in": [
          "1a",
          "1b"
        ]
      }
    }
  ]
})
  • Related