Update field in exact element array in MongoDB

MongodbMongodb QueryNosql

Mongodb Problem Overview


I have a document structured like this:

{
    _id:"43434",
    heroes : [
        { nickname : "test",  items : ["", "", ""] },
        { nickname : "test2", items : ["", "", ""] },
    ]
}

Can I $set the second element of the items array of the embedded object in array heros with nickname "test" ?

Result:

{
    _id:"43434",
    heroes : [
        { nickname : "test",  items : ["", "new_value", ""] }, // modified here
        { nickname : "test2", items : ["", "", ""] },
    ]
}

Mongodb Solutions


Solution 1 - Mongodb

You need to make use of 2 concepts: mongodb's positional operator and simply using the numeric index for the entry you want to update.

The positional operator allows you to use a condition like this:

{"heroes.nickname": "test"}

and then reference the found array entry like so:

{"heroes.$  // <- the dollar represents the first matching array key index

As you want to update the 2nd array entry in "items", and array keys are 0 indexed - that's the key 1.

So:

> db.denis.insert({_id:"43434", heroes : [{ nickname : "test",  items : ["", "", ""] }, { nickname : "test2", items : ["", "", ""] }]});
> db.denis.update(
    {"heroes.nickname": "test"}, 
    {$set: {
        "heroes.$.items.1": "new_value"
    }}
)
> db.denis.find()
{
    "_id" : "43434", 
    "heroes" : [
        {"nickname" : "test", "items" : ["", "new_value", "" ]},
        {"nickname" : "test2", "items" : ["", "", "" ]}
    ]
}

Solution 2 - Mongodb

Try update document in array using positional $,

The positional $ operator facilitates updates to arrays that contain embedded documents. Use the positional $ operator to access the fields in the embedded documents with the dot notation on the $ operator.

db.collection.update(
  { "heroes.nickname": "test" },
  { $set: { "heroes.$.items.1": "new_value" } },
  { multi: true }
);

Playground

Solution 3 - Mongodb

Try update with positional $ and $position,

db.collection.update(
  { heroes:{ $elemMatch:{ "nickname" : "test"} } },
  {
    $push: {
      'heroes.$.items': {
        $each: ["new_value" ],
        $position: 1
      }
    }
  }
)

Solution 4 - Mongodb

This solution works well. Just want to add one point. Here is the structure. I need to find OrderItemId is 'yyy' and update. If the query field in condition is an array, like below "OrderItems.OrderItemId" is array. You can not use "OrderItems.OrderItemId[0]" as operation in the query. Instead, you need to use "OrderItems.OrderItemId" to compare. Otherwise, it can not match one.

{
  _id: 'orderid',
  OrderItems: [
   {
     OrderItemId: ['xxxx'], 
    ... },
   {
     OrderItemId: ['yyyy'], 
    ...}, 
]
  
}
 result =  await collection.updateOne(
        { _id: orderId, "OrderItems.OrderItemId": [orderItemId] },
        { $set: { "OrderItems.$.imgUrl": imgUrl[0], "OrderItems.$.category": category } },
        { upsert: false },
      )
    console.log('  (result.modifiedCount) ', result.modifiedCount)
    console.log('  (result.matchedCount) ', result.matchedCount)

Solution 5 - Mongodb

go further! Use string template for paste your variable indexes in the way

   yourModel.findOneAndUpdate(
     { _id: "43434" },
     {
       $set: {
         [`heroes.${heroesIndex}.items.${itemIndex}`]: "new_value",
       },
     }
   );

or without template

   yourModel.findOneAndUpdate(
     { _id: "43434" },
     {
       $set: {
         'heroes.0.items.1': "new_value",
       },
     }
   );

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDenis ErmolinView Question on Stackoverflow
Solution 1 - MongodbAD7sixView Answer on Stackoverflow
Solution 2 - MongodbturivishalView Answer on Stackoverflow
Solution 3 - MongodbRubin PorwalView Answer on Stackoverflow
Solution 4 - MongodbKathy View Answer on Stackoverflow
Solution 5 - Mongodbuser14155923View Answer on Stackoverflow