Reputation: 175
I've a collection like this
db.aa1.insertMany([
{ parentArr: [] },
{ parentArr: [
{childArr: [ {childField: 2}, {childField: 4} ]}
] },
{ parentArr: [
{childArr: []}
] },
{ parentArr: [
{childArr: [ {childField: 3}, {childField: 5} ]}
] },
])
Now I want the end result to be like
[
{ parentArr: [] },
{ parentArr: [ { childArr: [] } ] },
{ parentArr: [
{
childArr: [ {childField: 2}, {childField: 4} ],
parentField: [2, 4]
},
] },
{ parentArr: [
{
childArr: [ {childField: 3}, {childField: 5} ],
parentField: [3, 5]
}
] },
]
Here I've copied the childArr.childField values in the parentArr.parentField.
Now in plain JS, I could do something like this
parentArr.forEach(p => p.parentField = p.childArr ? p.childArr.map(c => c.childField) : [])
How can I achieve this using a MongoDB Query?
I've tried the following $push $set combinations, of course, one at a time.
For the example sake, I've written all push and set together.
db.myCollection.update(
{
"parentArr.childArr.0": {$exists: true}
},
{
$set: {"parentArr.$[].parentField": ["$parentArr.$[].childArr.$[].childField"]}
$set: {"parentArr.parentField": ["$parentArr.childArr.childField"]}
$push: {
"parentArr.$[].parentField": {$each: ["$parentArr.$[].childArr.$[].childField"]}
}
$push: {
"parentArr.parentField": {$each: ["$parentArr.childArr.childField"]}
}
},
{
upsert: true,
multi: true
}
)
Upvotes: 1
Views: 278
Reputation: 22276
If you're using Mongo version 4.2+ they have introduced pipeline'd updates meaning we now have more power when updating:
db.aa1.updateMany(
{
"parentArr.childArr.childField": {$exists: true}
},
[
{
$set: {
"parentArr.parentField": {
$reduce: {
input: {
$map: {
input: "$parentArr",
as: "parent",
in: {
$map: {
input: "$$parent.childArr",
as: "child",
in: "$$child.childField"
}
}
}
},
initialValue: [],
in: {$setUnion: ["$$value", "$$this"]}
}
}
}
}
]
)
If you're on an older Mongo version then you'll have to do it in code, as you already posted a relevant snippet I have no more to add.
Upvotes: 1