Skip to content

Aggregation Fundamentals

$match

Filter early. The same operators as find(), and why putting $match first is not optional.

IntermediateAbout 4 minutes

$match is find's filter as a pipeline stage. Same operators: $gt, $in, $elemMatch. Put it as early as you can so $group and $lookup (later) see fewer documents. An early $match can use an index the same way find does.

db.orders.aggregate([
  { $match: { status: { $ne: "cancelled" } } },
  { $group: { _id: "$userId", totalSpent: { $sum: "$amount" } } }
])
Drop cancelled orders before you total anything

A $match after $group filters groups ({ totalSpent: { $gte: 10000 } }), not original orders. That is valid — 'customers who spent at least 10k' — and it is a different question from 'only completed orders in the sum'.

db.orders.aggregate([
  { $match: { status: "completed" } },
  { $group: { _id: "$userId", totalSpent: { $sum: "$amount" } } },
  { $match: { totalSpent: { $gte: 10000 } } }
])
Filter groups, not source rows

Interview question

Why put $match as early as possible in a pipeline?

Think about it first.

Practice