querydrill

Learn › Reference

How to think about an aggregation pipeline

Most people write pipelines by trial and error. These six questions decide the stages before you type anything - answer them in order and the pipeline usually falls out. The patterns after them are the shapes that recur often enough to recognise on sight.

For almost every question, ask these in order:

Question 1: Which documents do I need?

$match

Example:

Only completed orders from 2026.

Question 2: Is the data I need inside an array?

$unwind

Example:

Analyze products inside items.

Question 3: Do I need to combine multiple documents?

$group

Example:

Revenue per product.

Question 4: Do I need calculated fields?

$project
or
$set
or expressions inside $group

Example:

price × quantity

Question 5: How should the result look?

$project

Example:

Instead of:

{
  _id: "Laptop",
  revenue: 2000
}

You might want:

{
  product: "Laptop",
  revenue: 2000
}

Question 6: Do I need ranking/pagination?

$sort
$skip
$limit

Rapid pattern recognition

Worth being able to map on sight:

Problem Think
Filter documents $match
Keep/rename/calculate fields $project
Add a calculated field $set
Analyze elements inside an array $unwind
Count/sum/average by something $group
Order results $sort
Top N $sort → $limit
Pagination $sort → $skip → $limit
One overall total $group: { _id: null }

The five patterns worth memorising

Pattern 1 — Count by X

[
  {
    $group: {
      _id: "$someField",
      count: { $sum: 1 }
    }
  }
]

Pattern 2 — Sum by X

[
  {
    $group: {
      _id: "$someField",
      total: {
        $sum: "$amount"
      }
    }
  }
]

Pattern 3 — Array analytics

[
  {
    $unwind: "$items"
  },

  {
    $group: {
      _id: "$items.product",
      count: { $sum: 1 }
    }
  }
]

Pattern 4 — Top N

[
  {
    $group: {
      _id: "$category",
      total: {
        $sum: "$amount"
      }
    }
  },

  {
    $sort: {
      total: -1
    }
  },

  {
    $limit: 5
  }
]

Pattern 5 — Filter → Transform → Group → Sort

This is probably the most common pattern:

$match
   ↓
$unwind / $project / $set
   ↓
$group
   ↓
$project
   ↓
$sort
   ↓
$limit

Try it

All six questions, in order, in one pipeline - revenue per product from completed orders:

db.orders.aggregate([
  { $match: { status: "completed" } },
  { $unwind: "$items" },
  {
    $group: {
      _id: "$items.product",
      revenue: {
        $sum: {
          $multiply: ["$items.price", "$items.quantity"]
        }
      }
    }
  },
  {
    $project: {
      _id: 0,
      product: "$_id",
      revenue: 1
    }
  },
  { $sort: { revenue: -1 } },
  { $limit: 5 }
])

Delete stages from the bottom up and run it after each one. You are watching the six questions get answered in reverse, and it is the fastest way to learn to read someone else’s pipeline.

Other reference pages

MongoDB operator cheatsheet

Common aggregation mistakes

$match vs $filter, $project vs $map, $group vs $reduce