Advanced Aggregation
$facet
Run several pipelines on the same input: totals, buckets and samples in one round trip.
$facet runs several pipelines on the same input documents and returns one document whose fields are those results (each an array). One round trip for a dashboard: a total, a breakdown, a sample. Facets cannot see each other. They cannot $lookup each other's output.
db.products.aggregate([
{ $match: { inStock: true } },
{
$facet: {
total: [{ $count: "n" }],
byCategory: [
{ $group: { _id: "$category", n: { $sum: 1 } } },
{ $sort: { n: -1 } }
],
sample: [
{ $limit: 3 },
{ $project: { _id: 0, name: 1, price: 1 } }
]
}
}
]){
total: [{ n: 40 }],
byCategory: [{ _id: "electronics", n: 12 }, { _id: "books", n: 8 }, ...],
sample: [{ name: "Mechanical Keyboard", price: 4500 }, ...]
}$match before $facet so every branch is cheaper. A facet pipeline starts from that filtered set, not from the collection. Empty facet → { total: [], ... }. $count inside a facet still returns a one-element array. You cannot $unwind a sibling from inside another branch. Use $facet when the branches are independent; use one pipeline when the second stage needs the first's $group.
Interview question
What is $facet for, and what can a facet pipeline not do?
Several aggregations on the same input in one round trip — totals, groupings, a sample. Each branch is isolated: it cannot read another facet's output, nest another $facet, or $out. $match before $facet so every branch sees fewer documents.