0

I'd like to update a property from objects located in multiple lists on a MongoDB collection's document.

In a MongoDB collection I have documents like this one:

{
    "firstArray": [
        {
        "name": "john",
        "updated": false // I wanna switch that to true
        },
        {
        "name": "bob",
        "updated": false
        }
    ],
    "secondArray": [
        {
        "name": "eric",
        "updated": false
        },
        {
        "name": "john",
        "updated": false // I wanna switch that to true
        }
    ]
}

My goal is to update every element with "name":"john" from document's properties firstArray and secondArray to updated:true.

As they can be parallel accesses to a document, I shall only use update operators (a read and replace method like that one would add the risk of dropping changes made by another process)

It looks like the filtered positional operator $[] as mentioned in that question is the way to go to update an object's property from a document's Array BUT it appears that it doesn't support multiple $set with the same operator nor using two operators (one by array) in two different $set!

As this mongo shell command only update the secondArray:

    db['collection'].update(
    {},
    {
        "$set": { "firstArray.$[elem].updated": true },
        "$set": { "secondArray.$[elem].updated": true }
    },
    { "arrayFilters": [{ "elem.name": "john" }], "multi": true })

And this command returns The array filter for identifier 'a' was not used in the update { $set: { secondArray.$[b].updated: true } }:

    db['collection'].update(
    {},
    {
        "$set": { "firstArray.$[a].updated": true },
        "$set": { "secondArray.$[b].updated": true }
    },
    { "arrayFilters": [{ "a.name": "john" }, { "b.name": "john" }], "multi": true })

So, would you have any idea how to do that update? (Bonus point for any documentation quotes about the above limitations )

Thanks!

PaulCo
  • 1,398
  • 4
  • 17
  • 31

1 Answers1

2

The second argument to that function in an object. A given field name can only have one value in an object. To show what is being sent to the server, I assigned the value you are using to a variable:

> var o={    
     "$set": { "firstArray.$[a].updated": true },         
     "$set": { "secondArray.$[b].updated": true }     
}; 
> printjson(o)
{ "$set" : { "secondArray.$[b].updated" : true } }

As you can see, the first value was overwritten by the second because both fields were named $set.

Try combining these into a single field:

{
  "$set": { 
           "firstArray.$[elem].updated": true,
            "secondArray.$[elem].updated": true 
  }
}
Joe
  • 25,000
  • 3
  • 22
  • 44
  • How did I missed that? Thanks a bunch Joe! – PaulCo Mar 16 '20 at 20:59
  • I guess I misread the doc as [this update example](https://docs.mongodb.com/manual/reference/method/db.collection.update/#perform-conditional-updates-based-on-current-field-values) mentions two different `$set` (for a reason though) but [the actual page](https://docs.mongodb.com/manual/reference/operator/update/set/) for the `$set` operator clearly mention example to update different properties with a single use. – PaulCo Mar 17 '20 at 08:04