I’m trying to update an object in an array using the $elemMatch AND the $in operator on another array field.
My query looks like this:
var query = {array:{$in: ['second']},objectList: {$elemMatch: {toMatch: {$exists: true}}} };
db.foo.update(query, {$set: {'objectList.$.toChange':10}}, {multi: true})
If array is ["second","first"] the update operation will update the object as expected.
If array is ["first","second"] the update operation will append a new object in objectList instead of doing an update.
How to reproduce:
db.foo.insert({ "objectList" : [{"toChange" : 0.0,"toMatch" : "bar"}],"array" : ["first","second"] })
db.foo.insert({ "objectList" : [{"toChange" : 0.0,"toMatch" : "bar"}],"array" : ["second","first"] })
var query = {array:{$in: ['second']},objectList: {$elemMatch: {toMatch: {$exists: true}}} }
db.foo.update(query, {$set: {'objectList.$.toChange':10}}, {multi: true})
db.foo.find(query, {_id:0})
Returns:
{
"objectList" : [
{
"toChange" : 0.0,
"toMatch" : "bar"
},
{
"toChange" : 10.0
}
],
"array" : [
"first",
"second"
]
},
{
"objectList" : [
{
"toChange" : 10.0,
"toMatch" : "bar"
}
],
"array" : [
"second",
"first"
]
}
This has been tested on mongo db versions:
db.version() => 5.0.3
db.version() => 4.2.18
db.version() => 4.4.11
>Solution :
This one is working correctly:
db.collection.update({
array: {
$in: [
"second"
]
},
objectList: {
$elemMatch: {
toMatch: {
$exists: true
}
}
}
},
{
$set: {
"objectList.$[].toChange": 10
}
},
{
multi: true
})
Explained:
The $ need to be $[] , also $arrayFilters can be used here as well
but indeed it is an iteresting buggy behaviour of $