Ranjith Ranjith - 3 months ago 17
Node.js Question

Node.js - how to calculate the aggregate(sum) of sub document in mongodb?

My collection structure was,

[{
"_id": "....",
"name": "aaaa",
"level_max_leaves": [{
level: "ObjectIdString 1",
max_leaves: 4,
}]
}, {
"_id": "....",
"name": "bbbb",
"level_max_leaves": [{
level: "ObjectIdString 1",
max_leaves: 4,
}]
}, {
"_id": "....",
"name": "cccc",
"level_max_leaves": [{
level: "ObjectIdString 1",
max_leaves: 7,
}]
}, {
"_id": "....",
"name": "dddd",
"level_max_leaves": [{
level: "ObjectIdString 2",
max_leaves: 3,
}]
}]


Now I need to sum the field of
max_leaves
which has the
ObjectIdString 1
?

And the result of
(4+4+7=15)
.

so far I tried

var empLevelId = 1234... ;
MyModel.aggregate(
{$unwind: "$level_max_leaves.level"},
{$match: {"$level_max_leaves.level": empLevelId } },
{$group: { "_id": "$level_max_leaves.level",
"total": { "$sum": "$level_max_leaves.max_leaves" }}},
function (err, res) {
console.log(res);
});


How to achieve this?

Answer

Generally when dealing with arrays in the aggregation framework you need to $unwind the array contents first. This "de-normalizes" the content as individual documents. From here normal grouping operations work as expected:

MyModel.aggregate([

    // Unwind to "de-normalize"
    { "$unwind": "$level_max_leaves" },

    // Group as expected
    { "$group": {
        "_id": "$level_max_leaves.level",
        "total": { "$sum": "$level_max_leaves.max_leaves" }
    }}

],function(err,result) {

    // process results here

});

Note also that the "absolute" paths are required when addressing elements.