Reputation: 15104
I need to set a default value to my documents but only when the field does not exists. My problem is that I am using an array operator.
My request is like this :
db.myCollection.updateMany({}, { $set: { 'foo.$[].bar.$[].test': 42 }})
myCollection
contains the followings two documents:
{
foo: [
{ bar: [{ a: 1 }, { a: 2, test: 18 }] },
{ bar: [{ a: 1, test: 20 }, { a: 2, test: 18 }] }
]
}
{
foo: [
{ bar: [{ a: 1, test: 40 }, { a: 2, test: 18 }] },
{ bar: [{ a: 1, test: 20 }, { a: 2, test: 18 }] }
]
}
But if the property test
exists, I don't want to overwrite it. So in my example, I only want to set the default value of one subelement (in the first document).
How can i change my request to do it?
Upvotes: 1
Views: 1074
Reputation: 37048
Just for the sake of having an alternative to absolutely correct answer you can benefit from v4.2+ feature of using aggregation in updates. This update should do the same:
db.myCollection.updateMany({},
[
{
$set: {
foo: {
$map: {
input: "$foo",
as: "f",
in: {
$map: {
input: "$$f.bar",
as: "b",
in: {
$mergeObjects: [
{
test: 42
},
"$$b"
]
}
}
}
}
}
}
}
])
It would be great if you can compare performance of both updates.
Upvotes: 1
Reputation: 36104
You can use arrayFilters,
b
for bar
is existst
for test
is not existsdb.myCollection.updateMany(
{},
{ $set: { 'foo.$[b].bar.$[t].test': 42 } },
{
arrayFilters: [
{ "b.bar": { $exists: true } },
{ "t.test": { $exists: false } }
]
}
)
Upvotes: 3