Reputation: 1339
I have a collection like this
[{
"_id" : ObjectId("590c2331dc1a05e7d3525e70"),
"name" : "Orange",
"quarters" : {
"first" : 20,
"middle" : 53,
"last" : 52
}
}, {
"_id" : ObjectId("590c2405dc1a05e7d3525e71"),
"name" : "Apple",
"quarters" : {
"first" : 42,
"middle" : 37,
"last" : 16
}
}]
and I want result like this
[{
name: "Orange",
first: 20
},{
name: "Orange",
middle: 53
},{
name: "Orange",
last: 52
},{
name: "Apple",
first: 42
},{
name: "Apple",
middle: 37
},{
name: "Apple",
last: 16
}]
I tried to find the solution and I found few question similar to this question but no luck
Thanks in advance
Upvotes: 1
Views: 5577
Reputation: 75914
You can try below aggregation pipeline in 3.4.4
version.
Change the quarters
embedded document into array of key value pairs using $objectToArray
followed by $unwind
and $zip
each quarters
key value pair separately followed by $arrayToObject
to create original structure.
Use $addFields
to push the name
field into quarters
.
Use $replaceRoot
to promote the quarters
embedded document to top level.
db.collection.aggregate([
{$addFields: {quarters: {$objectToArray: "$quarters"}}},
{$unwind:"$quarters"},
{$addFields:{quarters: {"$arrayToObject":{$zip:{inputs:[["$quarters.k"], ["$quarters.v"]]}}}}},
{$addFields:{"quarters.name": "$name"}},
{$replaceRoot:{newRoot:"$quarters"}}
])
Upvotes: 9
Reputation: 2249
You can get it like this:
var inputCollection = [{
"_id" : ObjectId("590c2331dc1a05e7d3525e70"),
"name" : "Orange",
"quarters" : {
"first" : 20,
"middle" : 53,
"last" : 52
}
}, {
"_id" : ObjectId("590c2405dc1a05e7d3525e71"),
"name" : "Apple",
"quarters" : {
"first" : 42,
"middle" : 37,
"last" : 16
}
}];
var output = [];
inputCollection.forEach(function(obj){
for (var key in obj.quarters) {
if (obj.quarters.hasOwnProperty(key)) {
output.push({ name:obj.name, key: obj.quarters[key] });
}
}
});
console.log("The output is :", output); // It will print your desired output.
I hope this will help.
Thanks.
Upvotes: 1