Using $facet for Multiple Pipelines in MongoDB Aggregation
📖 Scenario: You work at a bookstore that keeps its sales data in a MongoDB collection called sales. Each document records a book sale with fields like title, genre, price, and copies_sold.The manager wants to see two things at once: the total revenue per genre and the top 3 best-selling books overall.
🎯 Goal: Build a MongoDB aggregation query using $facet to run two pipelines simultaneously:One pipeline calculates total revenue per genre.The other pipeline finds the top 3 best-selling books overall.
📋 What You'll Learn
Create a sales collection with exact documents provided.
Add a variable minCopies set to 5 to filter popular books.
Write an aggregation query using $facet with two pipelines: revenueByGenre and topBooks.
In revenueByGenre, group by genre and sum total revenue (price * copies_sold).
In topBooks, filter books with copies_sold >= minCopies, sort by copies_sold descending, and limit to 3.
Complete the aggregation query with the db.sales.aggregate() call.
💡 Why This Matters
🌍 Real World
Bookstores and retail businesses often need to analyze sales data in multiple ways simultaneously, such as revenue by category and best sellers.
💼 Career
Understanding $facet helps database developers and analysts write efficient queries that return multiple summaries in one request, saving time and resources.
Progress0 / 4 steps
1
Create the sales collection with sample data
Create a variable called sales and assign it an array of these exact documents: {"title": "Book A", "genre": "Fiction", "price": 10, "copies_sold": 4}, {"title": "Book B", "genre": "Fiction", "price": 15, "copies_sold": 7}, {"title": "Book C", "genre": "Non-Fiction", "price": 20, "copies_sold": 5}, {"title": "Book D", "genre": "Non-Fiction", "price": 25, "copies_sold": 3}, {"title": "Book E", "genre": "Fiction", "price": 8, "copies_sold": 10}
MongoDB
Hint
Create a list named sales with the exact book documents as shown.
2
Add a variable minCopies to filter popular books
Create a variable called minCopies and set it to 5.
MongoDB
Hint
Just create a variable named minCopies and assign 5 to it.
3
Write the aggregation query using $facet with two pipelines
Create a variable called aggregationQuery and assign it the MongoDB aggregation pipeline array that uses $facet with two pipelines: revenueByGenre and topBooks. In revenueByGenre, group by genre and sum total revenue as totalRevenue (calculate price * copies_sold). In topBooks, filter documents where copies_sold is greater than or equal to minCopies, sort by copies_sold descending, and limit to 3.
MongoDB
Hint
Use $facet with two pipelines named revenueByGenre and topBooks as described.
4
Complete the aggregation call with db.sales.aggregate()
Write a line of code that assigns to a variable called result the call to db.sales.aggregate() passing the aggregationQuery variable.
MongoDB
Hint
Call db.sales.aggregate() with aggregationQuery and assign to result.
Practice
(1/5)
1. What does the $facet stage do in a MongoDB aggregation pipeline?
easy
A. Sorts documents in ascending or descending order.
B. Filters documents based on a condition.
C. Joins two collections together.
D. Runs multiple pipelines on the same input data and returns results in one document.
Solution
Step 1: Understand the purpose of $facet
$facet allows running multiple aggregation pipelines on the same input data simultaneously.
Step 2: Identify the output structure
The output is a single document containing separate arrays for each pipeline's results.
Final Answer:
Runs multiple pipelines on the same input data and returns results in one document. -> Option D
Quick Check:
$facet = multiple pipelines, one output document [OK]
Hint: Remember: $facet runs many pipelines at once [OK]
Common Mistakes:
Thinking $facet filters or sorts data
Confusing $facet with $lookup
Assuming it returns multiple documents instead of one
2. Which of the following is the correct syntax to use $facet in a MongoDB aggregation pipeline?
$facet expects an object where each key is a pipeline name and the value is an array of pipeline stages.
Step 2: Check each option
{ $facet: { pipeline1: [ { $match: {} } ], pipeline2: [ { $group: {} } ] } } correctly uses an object with arrays of stages. Options A, C, and D misuse arrays or objects for stages.
A. The $facet stage must be the last stage in the pipeline.
B. You cannot use $group inside $facet.
C. Pipeline stages inside $facet must be arrays, not objects.
D. The field names inside $group are incorrect.
Solution
Step 1: Check $facet syntax requirements
Each pipeline inside $facet must be an array of stages, not a single object.
Step 2: Identify the error in the given code
The pipeline 'sales' is given as an object with $group, missing array brackets.
Final Answer:
Pipeline stages inside $facet must be arrays, not objects. -> Option C
Quick Check:
$facet pipelines = arrays of stages [OK]
Hint: Always wrap pipeline stages in arrays inside $facet [OK]
Common Mistakes:
Using object instead of array for pipeline stages
Assuming $group is disallowed inside $facet
Thinking $facet must be last stage
5. You want to get both the average price and a list of unique items from a products collection in one query. Which $facet pipeline correctly achieves this?
Each facet must be a named pipeline with an array of stages.
Step 2: Check each option
{ $facet: { avgPrice: [ { $group: { _id: null, avg: { $avg: "$price" } } } ], uniqueItems: [ { $group: { _id: "$item" } } ] } } correctly uses two pipelines: one groups to get average price, the other groups by item to get unique items. Options B, C, and D misuse arrays or operators incorrectly.