Aggregation Fundamentals
$match
Filter early. The same operators as find(), and why putting $match first is not optional.
$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" } } }
])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 } } }
])Interview question
Why put $match as early as possible in a pipeline?
Later stages process fewer documents. An early $match can use an index like find(). A $match after $group is for filtering groups, not original fields unless you accumulated them.
Practice