So the idea is to:
- Pick one of the array from
field3
say name
to generate array range [0, 1, 2, 3]
.
- Loop through
name
and value
array simultaneously to get an array of { k: "", v: "" }
.
$unwind
the array from previous stage for grouping.
- Group by key
field3.k
to accumulate all values field3.v
.
- Again group by
null
to generate an array of pattern { k: "", v: "" }
.
- Concatenate
field1
and field2
into the array from previous stage.
- 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
]
}