1

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
    }
)
0

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.