Skipm3
Skipm3

Reputation: 226

How to unwind array inside object in MongoDB?

I have about MongoDB in unwind operator.

So, I have document like this.

{
    "name": "abc",
    "report": {
        "_2019": {
            "May": {
                "_9": {
                    "DATA": [{
                            "image": "xyz.png",
                            "object": true
                        },
                        {
                            "image": "abc.png",
                            "object": true
                        }
                    ]
                },
                "_10": {
                    "DATA": [{
                            "image": "ejf.png",
                            "object": false
                        },
                        {
                            "image": "qwe.png",
                            "object": false
                        }
                    ]
                }
            },
            "June": {
                "_1": {
                    "DATA": [{
                        "image": "jsk.png",
                        "object": false
                    }]
                }
            }
        },
        "_2020": {
            "January": {
                "_30": {
                    "DATA": [{
                        "image": "hhg.png",
                        "object": false
                    }]
                }
            }
        }
    }
}

And want to format the output for something like this

[{
    "image": "xyz.png",
    "object": true
}, {
    "image": "abc.png",
    "object": true
}, {
    "image": "ejf.png",
    "object": false
}, {
    "image": "qwe.png",
    "object": false
}, {
    "image": "jsk.png",
    "object": false
}, {
    "image": "hhg.png",
    "object": false
}]

The first thing i found is that using unwind, but it only accept array. And the second is using foreach in the programming-side. But i think it's not effective. Is this possible? Thank you.

Upvotes: 6

Views: 2752

Answers (1)

mickl
mickl

Reputation: 49945

The problem here is that the keys like _2020 or January or _30 are dynamically generated. To access subdocuments from DATA level you need to get there by using $objectToArray and $map to take values from key-value pairs. After each of these steps you need $unwind and then in the last step you can run $replaceRoot to promote documents from DATA into root level:

db.col.aggregate([
    {
        $project: {
            data: {
                $map: {
                    input: { $objectToArray: "$report" },
                    in: "$$this.v"
                }
            }
        }
    },
    { $unwind: "$data" },
    {
        $project: {
            data: {
                $map: {
                    input: { $objectToArray: "$data" },
                    in: "$$this.v"
                }
            }
        }
    },
    { $unwind: "$data" },
    {
        $project: {
            data: {
                $map: {
                    input: { $objectToArray: "$data" },
                    in: "$$this.v"
                }
            }
        }
    },
    { $unwind: "$data" },
    { $unwind: "$data.DATA" },
    {
        $replaceRoot: {
            newRoot: "$data.DATA"
        }
    }
])

Mongo Playground

Upvotes: 3

Related Questions