I'm trying to update many objects within a nested array when their IDs exist in a list.
The document structure is like so:
{
id: p00,
children: [{
id: c00,
value: true
},
{
id: c01,
value: true
},
{
id: c02,
value: true
}
]
}
I would like to set value=false
if id=p00
and children.id
in [c00, c01]
.
This is my attempt, however it's clearly updating making only 1 update to the parent record, meaning only the c00
would be modified with the false value.
collection
.updateMany(and(
eq("id", "p00"),
in("children._id", [c00, c01])),
combine(
set("children.$.value", false)
));
Is this possible, or do I need to move the children up to make a more flatend structure? I'd prefer not to as that introduces it's own problems.
Thanks!
You can do it with pipeline update.
Pipeline updates allows us to use all aggregate operators, so we can do complicated updates (in your case maybe its possible with update operators also, but with pipeline its easy)
Pipelines updates require >= MongoDB 4.2.
Query
id=p00
$$c
variable) of the children array$$c.id
in the list ["c00","c01"]
$$c
with {"value" : false}
(its like add key value pair)$$c
db.collection.update({
"id": {
"$eq": "p00"
}
},
[
{
"$set": {
"children": {
"$map": {
"input": "$children",
"as": "c",
"in": {
"$cond": [
{
"$in": [
"$$c.id",
[
"c00",
"c01"
]
]
},
{
"$mergeObjects": [
"$$c",
{
"value": false
}
]
},
"$$c"
]
}
}
}
}
}
])
If you dont want to use update pipeline(your update is simple and it can be done with array filters also), and in Java would be like bellow.
coll.updateOne(new Document().append("id","p00"),
new Document().append("$set",new Document().append("children.$[item].value",false)),
new UpdateOptions().arrayFilters(
Collections.singletonList( Filters.in("item.id",Arrays.asList("c00","c01")))))