Aggregation Framework
The pipeline model
Aggregation is a pipeline of stages, each transforming a stream of documents: $match, $project, $addFields/$set, $group, $sort, $limit, $skip, $unwind, $lookup, $facet, $bucket, $count, $graphLookup, $out, $merge. $group uses _id as the grouping key (_id: null for a grand total) and accumulators $sum, $avg, $min, $max, $first, $last, $push, $addToSet.
Ordering matters for performance
Place $match and $sort as early as possible so they can use indexes; a $match after a $project that removes the field cannot use an index and cannot be moved by the optimizer. Only leading $match/$sort stages benefit from indexes; once the pipeline reshapes documents, everything is a scan.
Practical details
Each stage is limited to 100 MB of RAM; set allowDiskUse: true for large sorts and groups. $unwind explodes arrays into one document per element, multiplying row counts - a common source of inflated $group results. $lookup performs a left outer join, and its pipeline form (with let and $expr) filters the foreign documents. $facet runs sub-pipelines on the same input, useful for paginated results plus a total count.
Traps
$group does not preserve input order - add a final $sort. $sum: 1 counts documents; $sum: "$field" adds values. $out/$merge are only valid as terminal stages. $count fails on an empty input stream (it returns nothing), so callers must handle null.
Worked example
Revenue per customer: $match: {status: "paid"} → $unwind: "$items" → $group: {_id: "$customerId", revenue: {$sum: {$multiply: ["$items.price", "$items.qty"]}}} → $sort: {revenue: -1} → $limit: 10.