MongoDB Aggregations
MongoDB's aggregation pipeline lets you transform and analyze documents by passing them through a sequence of processing stages, each reshaping the data before it reaches the next.
What Is the Aggregation Pipeline?
Every aggregation operation in MongoDB is built around a pipeline: an ordered array of stages that documents flow through one at a time. Each stage takes the output of the previous stage as its input, applies some transformation such as filtering, grouping, or reshaping, and passes the result along. Because the stages run in sequence, the order you place them in matters enormously for both correctness and performance.
You invoke a pipeline with db.collection.aggregate(), passing an array of stage documents. Each stage is itself a document whose single key names the operator, for example $match, $group, $project, $sort, $limit, or $lookup. There is no limit on how many stages you can chain, though MongoDB does impose internal memory limits per stage unless you enable disk usage for large sorts and groups.
Why Not Just Use find()?
The find() method is excellent for retrieving documents that match a query, and it supports projections and simple sorting. But it cannot reshape documents, compute new fields from existing ones, join data across collections, or calculate aggregate statistics like sums, averages, or counts grouped by a key. The aggregation pipeline was built precisely to fill that gap, effectively giving you a data-processing language inside the database itself.
A Minimal Pipeline
db.orders.aggregate([
{ $match: { status: "completed" } },
{ $sort: { orderDate: -1 } },
{ $limit: 5 }
])This pipeline filters orders down to completed ones, sorts the survivors by date descending, and returns only the five most recent. Each stage narrows or reorders the working set before handing it to the next.
Combining Multiple Stage Types
Grouping and Reshaping Together
db.sales.aggregate([
{ $match: { region: "APAC" } },
{ $group: {
_id: "$product",
totalRevenue: { $sum: "$amount" },
orders: { $sum: 1 }
} },
{ $sort: { totalRevenue: -1 } },
{ $project: {
_id: 0,
product: "$_id",
totalRevenue: 1,
orders: 1
} }
])Here $match trims the input to a single region, $group computes per-product revenue and order counts, $sort ranks products by revenue, and $project renames and cleans up the final output shape. Notice how each stage builds directly on the field names produced by the one before it.
Joining a Related Collection
db.orders.aggregate([
{ $match: { status: "shipped" } },
{ $lookup: {
from: "customers",
localField: "customerId",
foreignField: "_id",
as: "customerInfo"
} },
{ $limit: 10 }
])Exercise: MongoDB Aggregations
How does data move through an aggregation pipeline?