Using Aggregation Framework
1. Understanding Pipeline Stages
| Concept | Detail |
|---|---|
| Pipeline | Array of stages, each transforms documents |
| Streaming | Docs flow stage-to-stage |
| Memory limit | 100MB per stage; use allowDiskUse: true to spill |
| Output | Cursor (default), or $out / $merge collection |
db.orders.aggregate([
{ $match: { status: "shipped" } },
{ $group: { _id: "$customerId", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } },
{ $limit: 10 }
], { allowDiskUse: true });
2. Matching Documents
| Aspect | Detail |
|---|---|
| Stage | $match: {filter} |
| Index use | Yes if first in pipeline |
| Best practice | $match early to reduce downstream work |
3. Projecting Fields
| Operator | Use |
|---|---|
| $project | Reshape, include/exclude, compute |
| $unset | Remove fields |
| $set / $addFields | Add fields without removing others |
4. Grouping Documents
| Aspect | Detail |
|---|---|
| Stage | $group: { _id, <accumulators> } |
| _id: null | Single group (totals) |
| _id: expr | Group key (string, doc, or computed) |
| Accumulators | $sum, $avg, $min, $max, $push, $addToSet, $first, $last, $count, $mergeObjects, $stdDev* |
5. Sorting Results
| Aspect | Detail |
|---|---|
| Stage | $sort: {field: 1|-1} |
| Memory | 100MB unless $sort+$limit (top-K) or index-backed |
| $sortByCount | Sort by group count desc |
6. Limiting Results
| Stage | Effect |
|---|---|
| $limit: n | Pass first n docs |
| Combined | $sort + $limit optimized to top-K |
7. Skipping Results
| Stage | Notes |
|---|---|
| $skip: n | Drops first n; O(n) cost |
| Pagination | Prefer range-based over skip for large offsets |
8. Unwinding Arrays
| Option | Effect |
|---|---|
| $unwind: "$arr" | One doc per element |
| preserveNullAndEmptyArrays | Keep docs with missing/empty arr |
| includeArrayIndex | Add element index field |
9. Looking Up from Collections
| Form | Use |
|---|---|
| Equality join | $lookup: {from, localField, foreignField, as} |
| Subquery / correlated | $lookup: {from, let, pipeline, as} |
| Outer join | $unwind with preserveNullAndEmptyArrays after |
| Performance | Index foreign field; small left side preferred |
10. Adding Computed Fields
| Stage | Detail |
|---|---|
| $addFields | Add or overwrite |
| $set | Alias of $addFields |
{ $addFields: { total: { $multiply: ["$qty", "$price"] }, taxed: { $round: [{ $multiply: ["$total", 1.08] }, 2] } } }
11. Replacing Root
| Stage | Effect |
|---|---|
| $replaceRoot: {newRoot: expr} | Promote subdoc to root |
| $replaceWith | Alias |
12. Counting Documents
| Stage | Effect |
|---|---|
| $count: "name" | Output: {name: N} |
| $group + $sum | Alternative for grouped counts |