How the engine optimizes pipelines in MongoDB - Performance & Efficiency
When MongoDB runs a pipeline, it tries to work faster by changing the order of steps or combining them.
We want to know how these changes affect the time it takes to finish the work.
Analyze the time complexity of this pipeline example.
db.collection.aggregate([
{ $match: { status: 'active' } },
{ $group: { _id: '$category', total: { $sum: '$amount' } } },
{ $sort: { total: -1 } }
])
This pipeline filters documents, groups them by category summing amounts, then sorts by total.
Look at what repeats as the data grows.
- Primary operation: Scanning documents to filter with $match.
- How many times: Once for each document in the collection.
- Next operation: Grouping documents by category, which depends on how many groups form.
- Sorting: Happens once on the grouped results, usually fewer than documents.
As the number of documents grows, the work changes like this:
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks and grouping on few items |
| 100 | About 100 checks and grouping on more items |
| 1000 | About 1000 checks and grouping on many items |
Filtering grows directly with documents, grouping depends on categories, sorting grows with groups but usually less than documents.
Time Complexity: O(n)
This means the time grows mostly in a straight line with the number of documents to check.
[X] Wrong: "The pipeline always runs slower if it has more steps, no matter what."
[OK] Correct: The engine can reorder or combine steps to keep things fast, so more steps don't always mean slower.
Understanding how pipelines get optimized helps you explain how databases handle big data efficiently.
"What if we moved the $match step after the $group? How would the time complexity change?"
Practice
Solution
Step 1: Understand pipeline stage purpose
MongoDB pipelines process data step-by-step. Filtering early reduces data size quickly.Step 2: Recognize optimization goal
Reordering stages to filter first means less data passes through later stages, speeding up processing.Final Answer:
To improve query performance by filtering data early -> Option CQuick Check:
Filtering early = better performance [OK]
- Thinking reordering changes output format
- Believing it adds fields automatically
- Assuming sorting is the main reason
Solution
Step 1: Identify correct $match placement
$match should come first to filter documents before grouping or sorting.Step 2: Check syntax order
[{$match: {status: "active"}}, {$group: {_id: "$category"}}] places $match first, then $group, which is correct syntax and optimization practice.Final Answer:
[{$match: {status: "active"}}, {$group: {_id: "$category"}}] -> Option AQuick Check:
$match first in pipeline = correct syntax [OK]
- Putting $match after $group or $sort
- Using $match inside $group stage
- Incorrect array order of stages
[{$project: {name: 1, age: 1}}, {$match: {age: {$gt: 30}}}], what will MongoDB do to optimize it?Solution
Step 1: Analyze pipeline stages
$project limits fields, $match filters documents. Filtering first reduces data early.Step 2: Understand optimization behavior
MongoDB reorders pipeline to apply $match before $project to reduce documents processed.Final Answer:
It will reorder to apply $match before $project -> Option AQuick Check:
Filter before project = better optimization [OK]
- Assuming stages stay in original order
- Thinking $project is removed
- Believing stages combine automatically
[{$group: {_id: "$category", total: {$sum: "$amount"}}}, {$match: {total: {$gt: 100}}}]. It runs slowly. What is the main issue?Solution
Step 1: Understand pipeline order impact
$group aggregates all documents first, then $match filters groups, causing more work.Step 2: Identify optimization fix
Filtering documents before grouping reduces data size and speeds up aggregation.Final Answer:
The $match stage should come before $group to filter documents early -> Option DQuick Check:
Filter before group = faster pipeline [OK]
- Thinking $group syntax is wrong
- Believing $sum can't be used in $group
- Assuming $sort affects speed here
[{$lookup: {from: "orders", localField: "_id", foreignField: "userId", as: "orders"}}, {$unwind: "$orders"}, {$match: {"orders.status": "shipped"}}, {$group: {_id: "$_id", total: {$sum: "$orders.amount"}}}]What is the best optimization to improve performance?
Solution
Step 1: Analyze pipeline stages
$lookup joins data, $unwind expands arrays, $match filters joined data, $group aggregates.Step 2: Identify optimization strategy
Filtering local documents before $lookup reduces join size, improving performance.Step 3: Understand why other options fail
$sort doesn't reduce data size, removing $unwind breaks structure, $project can't replace $lookup.Final Answer:
Move the $match stage before $lookup using a $match on the local collection -> Option BQuick Check:
Filter early before $lookup = best optimization [OK]
- Adding $sort expecting speedup
- Removing $unwind breaks data structure
- Replacing $lookup with $project is invalid
Ready to prove it?
Pass the test and this pattern moves unknown
