querydrill

Learn ›Aggregation ›Arrays in a pipeline

$unwind + $group

$group$match$sum$unwind

This is the pattern worth memorising outright. $match to cut the data down, $unwind to flatten the array, $group to aggregate the elements, $sort to rank the result - a large share of real aggregation questions are this shape with different field names.

Now we can solve:

Total quantity sold per product.

db.orders.aggregate([
  {
    $match: {
      status: "completed"
    }
  },

  {
    $unwind: "$items"
  },

  {
    $group: {
      _id: "$items.product",

      totalQuantity: {
        $sum: "$items.quantity"
      }
    }
  }
])

Let’s walk through it.

Stage 1 — $match

Only completed orders

Order 1
Order 2
Order 3

Stage 2 — $unwind

Order 1 → Laptop
Order 1 → Mouse
Order 2 → Keyboard
Order 3 → Laptop

Now the data looks conceptually like:

Laptop
Mouse
Keyboard
Laptop

Stage 3 — $group

Laptop
  quantity: 1 + 1 = 2

Mouse
  quantity: 2

Keyboard
  quantity: 1

Result:

[
  {
    _id: "Laptop",
    totalQuantity: 2
  },
  {
    _id: "Mouse",
    totalQuantity: 2
  },
  {
    _id: "Keyboard",
    totalQuantity: 1
  }
]

🚨 This Pattern Is Extremely Important

Memorize the concept, not the code:

Array of things

Need to analyze each thing individually?

        ↓

$unwind

        ↓

Now each array item behaves like
an individual pipeline document

        ↓

$group / $match / calculations

Examples:

Order
 └── items[]
User
 └── skills[]
Post
 └── comments[]
Invoice
 └── lineItems[]

Whenever the question is about individual elements inside an array, $unwind should enter your mind.

Practise this

1 exercise