Why aggregation operators matter in MongoDB - Performance Analysis
When using MongoDB, aggregation operators help process data in steps. Understanding their time cost helps us know how fast queries run as data grows.
We want to see how the work done changes when we use these operators on bigger data.
Analyze the time complexity of the following code snippet.
db.orders.aggregate([
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } }
])
This code filters orders by status, groups them by customer ID summing amounts, then sorts by total amount.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Scanning each document to filter and then grouping by customer.
- How many times: Each document is processed once in $match and $group stages; sorting processes all grouped results once.
As the number of orders grows, the work to filter and group grows roughly the same amount. Sorting depends on how many unique customers there are.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 scans, grouping a few customers, sorting few totals |
| 100 | About 100 scans, grouping more customers, sorting more totals |
| 1000 | About 1000 scans, grouping many customers, sorting many totals |
Pattern observation: The work grows roughly in step with the number of documents and unique groups.
Time Complexity: O(n log m)
This means the time to run grows a bit faster than the number of documents because of sorting after grouping, where m is the number of unique groups.
[X] Wrong: "Aggregation operators always run in linear time because they just process documents once."
[OK] Correct: Sorting after grouping can add extra time, making the total work grow faster than just scanning documents.
Knowing how aggregation stages affect time helps you explain your choices clearly and shows you understand how MongoDB handles data behind the scenes.
"What if we removed the $sort stage? How would the time complexity change?"
Practice
Solution
Step 1: Understand aggregation operators
Aggregation operators are used to process data and return computed results like sums, averages, and counts.Step 2: Compare with other operations
Inserting, deleting, and indexing are different operations unrelated to aggregation.Final Answer:
To summarize and analyze data quickly -> Option AQuick Check:
Aggregation = Summarize data [OK]
- Confusing aggregation with data insertion
- Thinking aggregation deletes data
- Mixing aggregation with indexing
Solution
Step 1: Review $group stage syntax
The $group stage groups documents and applies accumulators like $sum to fields.Step 2: Check correct $sum usage
$sum must be inside $group with a field path as "$fieldName" and an _id for grouping.Final Answer:
{ $group: { _id: null, total: { $sum: "$amount" } } } -> Option CQuick Check:
$sum inside $group with field path [OK]
- Placing $sum outside $group
- Missing quotes around field name
- Incorrect _id usage in $group
[{ $group: { _id: "$category", totalValue: { $sum: "$value" } } }]Solution
Step 1: Group documents by category
The $group stage groups documents by the "category" field, so we get groups for "A" and "B".Step 2: Sum the "value" fields per group
For category "A", sum is 10 + 20 = 30; for "B", sum is 5.Final Answer:
[{ "_id": "A", "totalValue": 30 }, { "_id": "B", "totalValue": 5 }] -> Option BQuick Check:
Sum values grouped by category [OK]
- Forgetting to group by category
- Summing all values without grouping
- Using null as _id incorrectly
[{ $group: { _id: "$category", total: { $sum: value } } }]Solution
Step 1: Check $sum syntax
The field name inside $sum must be a string with quotes, like "$value".Step 2: Validate other parts
Using $sum inside $group and _id as "$category" are correct; $match is optional.Final Answer:
Missing quotes around the field name "value" inside $sum -> Option AQuick Check:
Field names in $sum need quotes [OK]
- Omitting quotes around field names
- Thinking $sum can't be used in $group
- Assuming $match is mandatory first stage
Solution
Step 1: Filter scores greater than 50
The $match stage filters documents where "score" is greater than 50 before grouping.Step 2: Group by "team" and calculate average
The $group stage groups by "team" and calculates average "score" using $avg.Step 3: Verify other options
[{ $group: { _id: "$team", avgScore: { $avg: { $gt: ["$score", 50] } } } }] misuses $avg with $gt; [{ $group: { _id: "$team", avgScore: { $avg: "$score" } } }, { $match: { avgScore: { $gt: 50 } } }] filters after averaging, which is incorrect; [{ $match: { team: { $gt: 50 } } }, { $group: { _id: "$team", avgScore: { $avg: "$score" } } }] filters on "team" field incorrectly.Final Answer:
[{ $match: { score: { $gt: 50 } } }, { $group: { _id: "$team", avgScore: { $avg: "$score" } } }] -> Option DQuick Check:
Filter first, then group and average [OK]
- Filtering after grouping instead of before
- Misusing $avg with conditions inside
- Filtering wrong fields in $match
Ready to prove it?
Pass the test and this pattern moves unknown
