MongoDB Aggregation Pipeline
Parent: MongoDB Expert Knowledge · researched 2026-05-28T15:12:34.482Z· 11 sources · 10 concepts · skill mongodb-aggregation-pipeline
Stages execute left-to-right; each stage receives the document stream from the previous
1. Pipeline Stages Reference
2a. Equality join (localField / foreignField)
- MongoDB performs a hash-lookup on the foreign collection for each input document. [source]
- Always index the foreignField - without an index MongoDB scans the entire [source]
- foreign collection per input document (an O(N×M) table scan). [source]
- One important footgun: if the as field name already exists on the input document, [source]
- it is silently overwritten. Choose an as name that does not collide. [source]
- Required index on the foreign side: [source]
2b. Correlated sub-query (let + pipeline)
2c. Performance checklist for $lookup
- Index every foreignField (or the first field in the sub-pipeline $match). [source]
- Place $match inside the sub-pipeline to push filtering before the join materialises. [source]
- Avoid interleaving $unwind → $lookup → $unwind; chain all lookups, then unwind. [source]
- On sharded clusters, joining a sharded foreign collection is supported (MongoDB 5.1+), [source]
- but each input document fans out to every shard holding the foreign collection [source]
- (scatter-gather). Co-locate the collections on the same shard key, or use Atlas Data [source]
- Federation, to avoid the fan-out. [source]
3a. $out — full collection replacement
- $out atomically replaces the target collection after the full pipeline completes. [source]
- Use for nightly full rebuilds where brief stale reads are acceptable. [source]
- Target must be in the same database unless using { db, coll } object form (4.4+). [source]
- Reads see the old collection until the atomic swap completes. [source]
3b. $merge — incremental / upsert update
- $merge (introduced in 4.2) writes into an existing collection with [source]
- per-document conflict control. Ideal for incrementally updating materialized views. [source]
- whenMatched options: "replace" | "merge" | "keepExisting" | "fail" | [pipeline] [source]
- whenNotMatched options: "insert" | "discard" | "fail" [source]
- The [pipeline] form for whenMatched allows complex update logic: [source]
4a. Place $match (and $sort) early
4b. Project down early to shrink per-document size
- Large documents amplify memory usage across every downstream stage. [source]
5a. $expr in $match — field-to-field comparisons
5d. $accumulator — custom group-level accumulation
5e. $function — inline custom JavaScript per document
6. Window Functions ($setWindowFields)
7a. $densify — fill temporal gaps
7c. Native time series collections
9a. Default per-stage limit
9b. allowDiskUse
10c. Java — MongoDB Driver 5.x (sync)
References
- Aggregation Pipeline Stages - MongoDB Manual [source]
- $lookup (aggregation) - MongoDB Manual [source]
- $merge (aggregation stage) - MongoDB Manual [source]
- $setWindowFields - MongoDB Manual [source]
- $densify (aggregation stage) - MongoDB Manual [source]
- $fill (aggregation stage) - MongoDB Manual [source]
- Aggregation Pipeline Optimization - MongoDB Manual [source]
- Explain Results - MongoDB Manual [source]
- Time Series Collections - MongoDB Manual [source]
- $accumulator - MongoDB Manual [source]
- Aggregation with the Java Driver - MongoDB Docs [source]
Time Series Collection Aggregation Notes
- When running aggregation pipelines against time series collections (MongoDB 5.0+), the following behaviors differ from regular collections: [source]
- Bucket-level pruning: The query planner uses control.min/control.max metadata on internal buckets to skip entire buckets that don't match time-range or metaField predicates. Always place $match on the metaField and timeField as the first stage to maximise pruning. [source]
- $densify / $fill on time series: $densify partitionByFields supports dotted paths into metaField sub-fields but not measurement fields. For measurement field partitioning, use $addFields to promote the field before $densify. [source]
- $setWindowFields performance: Window functions do not push down through bucket storage. A tight $match before $setWindowFields is critical - without it, MongoDB unpacks and scans all buckets. [source]
- $dateTrunc for downsampling: Use $dateTrunc with binSize to downsample raw measurements into fixed time buckets (hourly/daily OHLCV, hourly averages). It is more efficient than $dateToString + $group for time-bucket aggregations. [source]
- $out to time series (MongoDB 7.0.3+): $out can write directly into a time series collection. $merge into a time series collection is not supported - use $out instead. [source]
- Cannot use distinct() on time series - use $group with a supporting metaField compound index instead. [source]
- For full time series aggregation patterns including IoT multi-sensor, financial OHLCV, gap-fill dashboards, and working set sizing, see mongodb-time-series. [source]
See also
- mongodb-aggregation-stages-deep - deep-dive reference for high-value stages: $lookup (equality, pipeline-with-let, Atlas Search), $graphLookup (recursive joins, tree/BOM patterns), $facet (16 MB ceiling, pagination idiom), $bucket/$bucketAuto (Renard / POWERSOF2 granularity), $merge/$out (materialized-view refresh, idempotency), $setWindowFields (rank, shift, derivative, integral), $densify/$fill (gap filling), $unionWith, plus 100 MB-per-stage memory limits, allowDiskUse, and explain("executionStats") spill detection. [source]
- mongodb-operations-expert (references/mongodb-spark-connector.md) - when an aggregation pipeline runs as part of a Spark/Databricks job. The connector accepts the same MQL aggregation pipeline syntax via the aggregation.pipeline read option, and Catalyst pushes Spark filters/projections/limit down by prepending $match/$project/$limit stages to the user-supplied pipeline. Pipeline tuning rules from this skill (index-backed $match first, $project early, allowDiskUse for large $sort/$group) apply identically. Use the Spark connector reference when the pipeline result becomes a DataFrame for downstream Spark work; stay in this skill for pipelines that run only inside the Mongo cluster. [source]
Children
- Pipeline Stages Reference (frontier)
- $lookup Patterns (frontier)
- $merge and $out Materialized Views (frontier)
- Pipeline Optimization (frontier)
- Aggregation Expressions (frontier)
- Window Functions ($setWindowFields) (frontier)
- Time Series Aggregation (frontier)
- Anti-Patterns (frontier)
- Memory Limits and allowDiskUse (frontier)
- Driver Examples (Node.js, Python, Java) (frontier)
- mongodb-time-series
Frontier under this node: $lookup Patterns, $merge and $out Materialized Views, Aggregation Expressions, Driver Examples (Node.js, Python, Java), Memory Limits and allowDiskUse, Pipeline Optimization, Pipeline Stages Reference, Time Series Aggregation, Window Functions ($setWindowFields)