Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert two array into an object in mongoDB where the first array has multiple same values

After some processing with a mongo aggregation, I have a collection like :

[{
 field1: 10,
 field2: 50,
 field3: { 
           name: ["a","b","a","a"], 
           value: [1,2,3,4]
         }
},...]

I am struggling finding a way to convert it into :

[{
 field1: 10,
 field2: 50,
 a:[1,3,4],
 b:[2]
},...]

Using mongo aggregation in mongoshell or compass

like image 477
Vee Avatar asked Nov 06 '22 02:11

Vee


1 Answers

So the idea is to:

  1. Pick one of the array from field3 say name to generate array range [0, 1, 2, 3].
  2. Loop through name and value array simultaneously to get an array of { k: "", v: "" }.
  3. $unwind the array from previous stage for grouping.
  4. Group by key field3.k to accumulate all values field3.v.
  5. Again group by null to generate an array of pattern { k: "", v: "" }.
  6. Concatenate field1 and field2 into the array from previous stage.
  7. Finally convert the array to object using $arrayToObject.

Try this:

db.testCollection.aggregate([
    {
        $addFields: {
            field3: {
                $map: {
                    input: { $range: [0, { $size: "$field3.name" }] },
                    as: "index",
                    in: {
                        k: { $arrayElemAt: ["$field3.name", "$$index"] },
                        v: { $arrayElemAt: ["$field3.value", "$$index"] }
                    }
                }
            }
        }
    },
    { $unwind: "$field3" },
    {
        $group: {
            _id: "$field3.k",
            field1: { $first: "$field1" },
            field2: { $first: "$field2" },
            k: { $first: "$field3.k" },
            v: { $push: "$field3.v" }
        }
    },
    {
        $group: {
            _id: null,
            field1: { $first: "$field1" },
            field2: { $first: "$field2" },
            array: {
                $push: { k: "$k", v: "$v" }
            }
        }
    },
    {
        $addFields: {
            array: {
                $concatArrays: [
                    [{ k: "field1", v: "$field1" }, { k: "field2", v: "$field2" }],
                    "$array"
                ]
            }
        }
    },
    {
        $replaceRoot: {
            newRoot: { $arrayToObject: "$array" }
        }
    }
]);

Output

{
    "field1" : 10,
    "field2" : 50,
    "a" : [
        1,
        3,
        4
    ],
    "b" : [
        2
    ]
}
like image 163
Dheemanth Bhat Avatar answered Nov 15 '22 05:11

Dheemanth Bhat