Mongoose Aggregation – Count, Group, Match, Project

In this blog post we will see about mongodb aggregation operations and how to use it with mongoose.

“Aggregations are operations that process data records and return computed results.”
These are operations like sum, count, average, group etc where we need to generated grouped results out of collection.
MongoDB exposes a pipeline based framework for aggregations, which looks something like below.

db.collection.aggregrate([
   pipe1_operator : {....},
   pipe2_operator : {....},
   pipe3_operator : {....}
])

Mongo provides various pipe operators like $match, $group, $project, $limit, $skip, $sort etc which we can use to do our computations.
More detailed explanation of Pipeline Framework can be found here and a list of all aggregation operations here

Lets look at various aggregation operations with examples. We will use collection schema as defined below

var isd_schema = mongoose.Schema({}, {
    strict: false,
    collection: 'isds'
});
var isd_model = conn.model('isds', isd_schema);

$group

Count the number of Users Belonging To A Particular Region

isd.aggregate([
        {
            $group: {
                _id: '$region',  //$region is the column name in collection
                count: {$sum: 1}
            }
        }
    ], function (err, result) {
        if (err) {
            next(err);
        } else {
            res.json(result);
        }
    });

More detailed explanation here There are various other operator which can be used with $group like $push, $$ROOT which are explained in the previous link.

$match

$match acts as a where condition to filter out documents.
Number of users who joined last month

var time = new Date().getTime() - 30 * 24 * 60 * 60 * 1000;
    isd.aggregate([
        {
            $match: {
                created: {$gt: new Date(time)}
            }
        },
        {
            $group: {
                _id: null,
                count: {$sum: 1}
            }
        }
    ], function (err, result) {
        if (err) {
            next(err);
        } else {
            res.json(result);
        }
    });

More detailed explanation here

$project

$project is used to add columns dynamically to the collection and use it for further aggregation.
Number of User Registering Per Month

isd.aggregate([
        {
            $project: {
                month: {$month: "$created"}
            }
        }, {
            $group: {
                _id: "$month",
                users: {$sum: 1}
            }
        }
    ], function (err, result) {
        if (err) {
            next(err);
        } else {
            res.json(result);
        }
    });

A More detailed explanation here

Count

Count Number of User who belong to a certain region

    isd.count({
        region: 'North'
    }, function (err, result) {
        if (err) {
            next(err);
        } else {
            res.json(result);
        }
    });

Distinct

Find all distinct regions

    isd.distinct("region", function (err, result) {
        if (err) {
            next(err);
        } else {
            res.json(result);
        }
    });

Overall mongodb aggregation is a very powerful tool for generating reports, summaries and other uses. There are many more pipeline operators than dicussed above, which can be seen here http://docs.mongodb.org/manual/reference/operator/aggregation/#aggregation-expression-operators