MongoDB Aggregation Pipeline Patterns

Group, project, sort, unwind, lookup, facet, and aggregate analytics data with MongoDB pipelines.

View
StandardDetailedCompact
Export
Copy the compact sheet, download it, or print it.
Download
`D` dense toggle · `C` copy all

Core stages

The stages most developers use first.

Sum revenue by status

Filter first, then group and sum.

javascriptANYmongodbaggregategroupsum
javascript
db.orders.aggregate([
  { $match: { status: "paid" } },
  { $group: { _id: "$country", revenue: { $sum: "$total" }, orders: { $sum: 1 } } },
  { $sort: { revenue: -1 } }
])
Notes

`$match` early in the pipeline can reduce the amount of work later stages perform.

Project computed fields

Shape output and derive new values.

javascriptANYmongodbaggregateproject
javascript
db.orders.aggregate([
  { $project: { customer_id: 1, total: 1, tax: { $multiply: ["$total", 0.08] } } }
])
Notes

`$project` is useful for output shaping and lightweight computed fields.

Unwind an array

Turn array elements into separate pipeline rows.

javascriptANYmongodbaggregateunwind
javascript
db.orders.aggregate([
  { $unwind: "$items" },
  { $group: { _id: "$items.sku", units: { $sum: "$items.qty" } } },
  { $sort: { units: -1 } }
])
Notes

`$unwind` is essential for analytics on nested arrays.

Join with another collection

Use `$lookup` for collection-to-collection joins.

javascriptANYmongodbaggregatelookupjoin
javascript
db.orders.aggregate([
  {
    $lookup: {
      from: "users",
      localField: "user_id",
      foreignField: "_id",
      as: "user"
    }
  },
  { $unwind: "$user" }
])
Notes

`$lookup` is the MongoDB pipeline equivalent of a join.

Advanced stages

Useful patterns for dashboards and analytics endpoints.

Run multiple result sets with $facet

Produce multiple related aggregations in one pipeline.

javascriptANYmongodbaggregatefacet
javascript
db.orders.aggregate([
  {
    $facet: {
      totalsByStatus: [
        { $group: { _id: "$status", count: { $sum: 1 } } }
      ],
      recentOrders: [
        { $sort: { created_at: -1 } },
        { $limit: 5 }
      ]
    }
  }
])
Notes

`$facet` is handy when one request needs several summary blocks.

Bucket data for reporting

Group values into explicit ranges.

javascriptANYmongodbaggregatebucket
javascript
db.orders.aggregate([
  {
    $bucket: {
      groupBy: "$total",
      boundaries: [0, 50, 100, 500, 1000],
      default: "1000+",
      output: { count: { $sum: 1 } }
    }
  }
])
Notes

Bucketing is useful for histograms and pricing summaries.

Count pipeline output

Return a final count after filters and transforms.

javascriptANYmongodbaggregatecount
javascript
db.orders.aggregate([
  { $match: { status: "paid" } },
  { $count: "paid_orders" }
])
Notes

`$count` is a concise finishing stage for reporting queries.

Recommended next

No recommendations yet.