Learn How to use Mongoose aggregation


In this article, you are going to learn about Mongoose aggregation.

In MongoDB, the aggregation pipeline consists of stages and each stage transforms the document. It is extremely powerful and very handy to use. Mongoose comes with aggregate() function by which you can use MongoDB’s aggregation framework with Mongoose. Basically, it is a thin wrapper and you can work any aggregation query in mongoose that works in mongoDB shell without making any changes.

Introduction to aggregation framework :

Aggregation Framework is a way to query the data from MongoDB. It helps you to query the complex logic into a simple set of sequential operations. Semantically, an aggregation framework query is an array of stages. A stage is an objective description that helps MongoDB to transform any document which is coming into the stage. The documents are feeding one stage to another to transform and when you pass the array of stages into an aggregate function() is called an aggregation pipeline.

There are different aggregate stages. The first one is the $match stage. It basically filters the documents that match the given filter parameter and filters out that doesn’t match. For example :

await Students.create([
  { name: 'John', age: 19, roll: '3' },
  { name: 'Alex', age: 21, roll: '6' },
  { name: 'Deven', age: 18, roll: '7' },
  { name: 'Carry', age: 19, roll: '19' },
  { name: 'David', age: 17, roll: '4' }
]);

const filter = { age: { $gte: 20 } };
let docs = await Students.aggregate([
  { $match: filter }
]);

docs.length; // 1
docs[0].name; // 'Alex'
docs[0].age // 21

You can not only just filter the documents but also use the aggregation framework to transform documents. For example, you want to count how many characters have a given age. To perform this you can use the $group stage like this :

let docs = await Students.aggregate([
  {
    $group: {
      // Each `_id` must be unique, so if there are multiple
      // documents with the same age, MongoDB will increment `count`.
      _id: '$age',
      count: { $sum: 1 }
    }
  }
]);

docs.length; // 4
docs.sort((d1, d2) => d1._id - d2._id);
docs[0]; // { _id: 19, count: 2 }
docs[1]; // { _id: 21, count: 1 }
docs[2]; // { _id: 18, count: 1 }
docs[3]; // { _id: 17, count: 1 }

You can combine multiple stages in one aggregation function. For example, if you want to combine the previous two examples to only group characters by age if their age is < 20.

let docs = await Students.aggregate([
  { $match: { age: { $lt: 20 } } },
  {
    $group: {
      _id: '$age',
      count: { $sum: 1 }
    }
  }
]);

docs.length; // 3
docs.sort((d1, d2) => d1._id - d2._id);
docs[0]; // { _id: 19, count: 2 }
docs[1]; // { _id: 18, count: 1 }
docs[2]; // { _id: 17, count: 1 }

Besides these, there are tons of stages in mongoose, some of them are $project, $skip, $limit, $unwind, $out, and so on. These are extremely powerful and you can use them in your function as the example above. Moreover, Mongoose middleware also let you perform pre(‘aggregate’) and post(‘aggregate’) hooks. You can use aggregation middleware to transform the aggregation pipeline.

Note : The limit per aggregation stage is up to 100 MB. If you exceed this limit, You will get an error from the database.If you really need to increase the limit you can opt to page to disk but there’s a disadvantage to using it because it is slower to work in the disk rather than memory.

This is all about mongoose aggregate. The more you practice with this, the more you can know that how extremely powerful it is.


Share on social media

//