1

I'm would like to do a data transformation using MongoDB Aggregation Framework. I'm stuck for several hours and can't seem to get my head around it.

Sample input data:

{
  a1: "value a1",
  a2: "value a2"
},
{
  a1: "value a3",
  a2: "value a4"
},
{
  a1: "value a5",
  a2: "value a6"
}

I would like to have the output below.

{
  a1: ["value a1", "value a3", "value a5"],
  a2: ["value a2", "value a4", "value a6"]
}

1 Answer 1

2

I'm assuming you want to run such aggregation dynamically (not knowing key names). In such case you need to start with $objectToArray, then run double $group to get an array for each key and in the last step you need to run $arrayToObject to get back key names as keys:

db.collection.aggregate([
    {
        $project: {
            doc: {
                $filter: {
                    input: { $objectToArray: "$$ROOT" },
                    cond: { $ne: [ "$$this.k", "_id" ] }
                }
            }
        }
    },
    {
        $unwind: "$doc"
    },
    {
        $group: {
            _id: "$doc.k",
            values: { $push: "$doc.v" }
        }
    },
    {
        $group: {
            _id: null,
            data: { $push: { k: "$_id", v: "$values" } }
        }
    },
    {
        $replaceRoot: {
            newRoot: {
                $arrayToObject: "$data"
            }
        }
    }
])

Mongo Playground

EDIT: the problem becomes very simple if you know the names of the keys:

db.collection.aggregate([
    {
        $group: {
            _id: null,
            a1: { $push: "$a1" },
            a2: { $push: "$a2" }     
        }
    }
])
Sign up to request clarification or add additional context in comments.

3 Comments

I know the key names. It worked! I'm a MongoDB noob and now I need to do a clean up of the arrays where I need to remove all empty (space) values. Poor data quality from a CSV import. Can this be done using the same aggregation pipeline? eg. { a1: ["", "", "value of a1", "value of a3", "value of a5", "", ""] } to { a1: ["value of a1", "value of a3", "value of a5"] }
@Chester try with $filter, here's an example: mongoplayground.net/p/sWIfQ8d3XcD
Managed to make it work thanks to your example. Really appreciate it! @mickl

Your Answer

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