LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 3318 min read

Advanced Aggregation Pipelines

Combine multiple stages into a complete, real-world reporting pipeline, and learn $facet, $bucket, and $unwind for arrays.

$unwind for Array Fields

Beyond flattening a $lookup result, $unwind can deconstruct any array field, producing one output document per array element — useful for analyzing individual items within an order, for example.

db.orders.aggregate([
{ $unwind: "$items" },
{ $group: { _id: "$items.product", totalSold: { $sum: "$items.quantity" } } },
{ $sort: { totalSold: -1 } },
]);

$facet: Multiple Pipelines at Once

$facet runs several independent sub-pipelines against the same input documents in one pass, returning all their results together — useful for building a single response that needs, say, both paginated results and a total count.

db.products.aggregate([
{ $match: { category: "electronics" } },
{
$facet: {
paginatedResults: [{ $skip: 0 }, { $limit: 10 }],
totalCount: [{ $count: "count" }],
},
},
]);

$bucket for Histograms

$bucket groups documents into ranges you define — the standard way to build a histogram, like grouping products into price bands.

db.products.aggregate([
{
$bucket: {
groupBy: "$price",
boundaries: [0, 25, 50, 100, 500],
default: "500+",
output: { count: { $sum: 1 } },
},
},
]);

A Complete Real-World Pipeline

Putting several stages together: a monthly sales report by product category, joining product details, filtering, grouping, and sorting.

db.orders.aggregate([
{ $match: { status: "completed", createdAt: { $gte: ISODate("2026-01-01") } } },
{ $unwind: "$items" },
{
$lookup: {
from: "products",
localField: "items.productId",
foreignField: "_id",
as: "productInfo",
},
},
{ $unwind: "$productInfo" },
{
$group: {
_id: "$productInfo.category",
totalRevenue: { $sum: { $multiply: ["$items.quantity", "$productInfo.price"] } },
unitsSold: { $sum: "$items.quantity" },
},
},
{ $sort: { totalRevenue: -1 } },
]);

Common Beginner Mistakes

Building an enormous pipeline in one attempt without testing each stage

Comment out later stages and run just the first few to verify each transformation as you build up a complex pipeline — debugging a full pipeline's wrong output all at once is much harder.

Forgetting $unwind on an array before grouping by an item within it

Without unwinding first, $group would treat the whole array as a single value rather than processing each item individually.

FAQs

No hard limit on stage count, though very long pipelines are worth reviewing for opportunities to filter earlier or simplify.

Yes — the $merge and $out stages write pipeline output directly into a (new or existing) collection, useful for materializing a computed report.

Summary

$unwind, $facet, and $bucket round out the aggregation framework's toolkit for genuinely complex reporting and analysis pipelines. With the aggregation framework covered, the next section moves into integrating MongoDB with a real application via Mongoose.

Next Lesson →

Introduction to Mongoose