Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB update Query in a loop

Tags:

mongodb

I am working with MongoDB in one of my project. For the next feature I need to add a flag to array of objects by looping with a matching condition.

Following is an example of document that I have -

{
    "_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
    "colors" : [
       { "status" : "done" },
       { "status" : "done" },
       { "status" : "n/a" }
   ]        
}

Output should be -

{
   "_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
   "colors" : [
       {
           "status" : "done",
           "is_in_production" : true
       }, 
       {
           "status" : "done",
           "is_in_production" : true
       },
       {
        "status" : "n/a"
       }
   ]
}

I used the following query -

db.getCollection('products').update( 
   {
       "colors.status": {
          "$in":[
             "done"
          ]
       }
   },
   {$set: { 'colors.$[].is_in_production' :true }},
   {multi: true}
)

That resulted the following error -

cannot use the part(colors of colors.$[].is_in_production)totraversetheelement({ colors: [{ "status" : "done" }, { "status" : "done" }, { "status" : "n/a" }] )}

Can someone help me with the query?? Thanks in Advance

like image 483
Bishwarup Das Avatar asked Feb 13 '26 14:02

Bishwarup Das


2 Answers

Use updateMany together with arrayFilters to update multiple documents in an array

db.products.updateMany(
   { "colors.status": "done" },
   { $set: { "colors.$[element].is_in_production" : true}},
   { arrayFilters: [{"element.status" : "done"}]}
)
like image 121
Clement Amarnath Avatar answered Feb 16 '26 15:02

Clement Amarnath


Use arrayFilters to update only a subset of embedded documents.

Try this query:

db.products.update(
{
   "colors.status": {
      "$in":[
         "done"
        ]
     }
  },
  {$set: { 'colors.$[element].is_in_production' :true }},
  {multi: true, arrayFilters:[{"element.status":"done"}]}
)

Output is:

/* 1 */
{
"_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
"colors" : [ 
    {
        "status" : "done",
        "is_in_production" : true
    }, 
    {
        "status" : "done",
        "is_in_production" : true
    }, 
    {
        "status" : "n/a"
    }
  ]
}

enter image description here

Note that you need MongoDB 3.6 and need to execute on latest shell (no third party tools preferably) in order for the arrayFilters to work properly.

If the above query isn't working for your Mongo version, try this query:

db.sample.findAndModify({
  query:{
     "colors.status": {
        "$in":[
           "done"
        ]
     }
 },
 update:{$set: { 'colors.$[element].is_in_production' : true }},
 multi: true, 
 arrayFilters:[{"element.status":"done"}]
})
like image 21
Rahul Raj Avatar answered Feb 16 '26 15:02

Rahul Raj