Why advanced stages matter in MongoDB - Performance Analysis
When using MongoDB's aggregation, each stage processes data and passes results to the next. Understanding how time grows with each stage helps us see why advanced stages matter.
We want to know how adding more stages affects the total work done.
Analyze the time complexity of this aggregation pipeline with multiple stages.
db.collection.aggregate([
{ $match: { status: "active" } },
{ $group: { _id: "$category", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } },
{ $limit: 5 }
])
This pipeline filters documents, groups them by category summing amounts, sorts by total, and limits output to top 5.
Look at what repeats as data flows through stages.
- Primary operation: Scanning documents in $match and grouping in $group.
- How many times: Each document is processed once per stage until filtered out.
As the number of documents grows, each stage processes more data, increasing total work.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 operations per stage |
| 100 | About 100 operations per stage |
| 1000 | About 1000 operations per stage |
Pattern observation: Work grows roughly in direct proportion to input size for each stage.
Time Complexity: O(n log n)
This means the total work grows roughly in proportion to n log n due to the $sort stage.
[X] Wrong: "Adding more stages doesn't affect performance much because each stage only does a small task."
[OK] Correct: Each stage processes data, so more stages mean more passes over data, increasing total work.
Understanding how each stage adds to total work helps you explain real MongoDB queries clearly and shows you think about efficiency in data processing.
"What if we added an extra $project stage before $group? How would that change the time complexity?"
Practice
Solution
Step 1: Understand the purpose of advanced stages
Advanced stages in MongoDB aggregation allow processing data in steps like filtering, grouping, and sorting.Step 2: Identify the benefit of step-by-step processing
This stepwise processing helps produce clear and useful results from complex data.Final Answer:
To process data step-by-step for clearer results -> Option AQuick Check:
Advanced stages = step-by-step processing [OK]
- Confusing aggregation stages with indexing
- Thinking advanced stages create backups
- Believing stages store data in collections
Solution
Step 1: Recall the aggregation method syntax
The aggregation pipeline starts with db.collection.aggregate() and takes an array of stages.Step 2: Check the correct use of $match stage inside an array
The $match stage must be inside an array as the first element to filter documents.Final Answer:
db.collection.aggregate([{ $match: { age: { $gt: 25 } } }]) -> Option CQuick Check:
aggregate() takes an array of stages [OK]
- Using find() instead of aggregate() for pipeline
- Passing object instead of array to aggregate()
- Using non-existent match() method
db.sales.aggregate([
{ $match: { qty: { $gt: 5 } } },
{ $project: { item: 1, _id: 0 } }
])Solution
Step 1: Apply the $match stage filtering qty > 5
Only the document with qty 10 (banana) matches the condition.Step 2: Apply the $project stage to include item and exclude _id
The output will show only the item field for the matched document.Final Answer:
[{ item: 'banana' }] -> Option BQuick Check:
Filter qty > 5 then project item only [OK]
- Including documents with qty <= 5
- Forgetting to exclude _id field
- Projecting fields before filtering
db.orders.aggregate([
{ $group: { _id: '$customerId', total: { $sum: '$amount' } } },
{ $sort: { total: -1 } },
{ $match: { total: { $gt: 100 } } }
])Solution
Step 1: Analyze the $group stage
It correctly groups by customerId and computes the total sum per customer.Step 2: Verify $sort and $match stages
$sort by total descending after $group is valid. $match filtering groups with total > 100 after $group is also valid on computed fields.Final Answer:
No error, pipeline is correct -> Option DQuick Check:
$match after $group on aggregates is allowed [OK]
- Thinking $match must always precede $group
- Believing $sort cannot follow $group
- Assuming $match cannot filter computed fields
Solution
Step 1: Group sales by product and sum amounts
The $group stage aggregates total sales per product correctly.Step 2: Sort products by totalSales descending and limit to top 3
$sort orders by totalSales descending, then $limit picks top 3 products.Final Answer:
[{ $group: { _id: '$product', totalSales: { $sum: '$amount' } } }, { $sort: { totalSales: -1 } }, { $limit: 3 }] -> Option AQuick Check:
Group, then sort, then limit for top results [OK]
- Limiting before grouping loses data
- Sorting before grouping gives wrong totals
- Placing $limit before $sort causes wrong output
Ready to prove it?
Pass the test and this pattern moves unknown
