Applications and events
Build an aggregation pipeline
Transform documents in small stages with match, unwind, group, project, and sort while keeping early filtering visible.
9 minute lesson
An aggregation pipeline passes documents through ordered stages. Each stage filters, reshapes, groups, joins, or calculates data for the next stage. It is how you answer questions that find() cannot, like “what are the five most popular favorite foods among dogs?”
Build it one stage at a time, inspecting output after each addition. Start by filtering:
db.animals.aggregate([
{ $match: { species: 'dog' } }
])
// full dog documents, unchanged
Each dog has a favoriteFoods array. $unwind turns one document with three foods into three documents with one food each — that gives $group something to count:
db.animals.aggregate([
{ $match: { species: 'dog' } },
{ $unwind: '$favoriteFoods' },
{ $group: { _id: '$favoriteFoods', count: { $sum: 1 } } }
])
// [ { _id: 'biscuits', count: 12 }, { _id: 'carrots', count: 9 }, ... ]
Note the '$favoriteFoods' syntax: inside a pipeline, a string starting with $ refers to a field’s value. Finish with ordering and a bound:
db.animals.aggregate([
{ $match: { species: 'dog' } },
{ $unwind: '$favoriteFoods' },
{ $group: { _id: '$favoriteFoods', count: { $sum: 1 } } },
{ $sort: { count: -1 } },
{ $limit: 5 }
])
That is the report: top five foods, most popular first.
Stage order is performance
Place selective $match stages as early as possible. A $match at the start of the pipeline can use an index on the collection. The same condition placed after a $group cannot — by then the original documents are gone and MongoDB has already processed the entire collection to build the groups.
The failure mode looks like this: the pipeline returns correct results in development, then takes thirty seconds on the production collection with two million documents. Running the same pipeline with .explain() shows a COLLSCAN feeding the first stage. The fix is usually moving a filter earlier, or adding the index the early $match needs.
Keep each stage small enough to inspect on its own. And keep expectations honest: aggregation is powerful, but it does not make an unbounded data model or a missing index disappear. A pipeline that compensates for a bad document shape on every read is a signal to fix the shape.
Lesson completed