$unwind for flattening arrays in MongoDB - Time & Space Complexity
When using $unwind in MongoDB, we want to understand how the work grows as the array size grows.
We ask: How does flattening arrays affect the number of operations?
Analyze the time complexity of the following MongoDB aggregation using $unwind.
db.orders.aggregate([
{ $match: { status: "active" } },
{ $unwind: "$items" },
{ $group: { _id: "$items.productId", totalQty: { $sum: "$items.qty" } } }
])
This pipeline filters active orders, then flattens the items array so each item is a separate document, and finally groups by product ID.
Look for repeated work inside the pipeline.
- Primary operation:
$unwindrepeats work for each element in theitemsarray. - How many times: Once per array element in each matched document.
As the number of array elements grows, the work grows proportionally.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 items per document | About 10 operations per document |
| 100 items per document | About 100 operations per document |
| 1000 items per document | About 1000 operations per document |
Pattern observation: The number of operations grows linearly with the number of array elements.
Time Complexity: O(n)
This means the time to unwind grows directly with the number of elements in the arrays being flattened.
[X] Wrong: "$unwind runs once per document regardless of array size."
[OK] Correct: Actually, $unwind processes each element inside the array separately, so more elements mean more work.
Understanding how $unwind scales helps you explain data processing costs clearly and shows you know how MongoDB handles arrays internally.
"What if we replaced $unwind with $project to keep arrays as is? How would the time complexity change?"
Practice
$unwind stage do in a MongoDB aggregation pipeline?Solution
Step 1: Understand the purpose of
$unwind$unwindtakes an array field and creates a new document for each element in that array.Step 2: Compare with other pipeline stages
Grouping, sorting, and removing duplicates are done by other stages like$group,$sort, and$match, not$unwind.Final Answer:
It turns each element of an array field into a separate document. -> Option AQuick Check:
$unwindflattens arrays = B [OK]
- Confusing $unwind with $group or $sort
- Thinking $unwind removes duplicates
- Assuming $unwind sorts documents
$unwind on the field items in an aggregation pipeline?Solution
Step 1: Recall correct
The$unwindsyntax$unwindstage requires the field path as a string with a $ prefix inside an object with keypath.Step 2: Evaluate each option
{ $unwind: "$items" } misses thepathkey. { $unwind: items } lacks quotes and $ prefix. { $unwind: { path: "items" } } misses the $ prefix. Only { $unwind: { path: "$items" } } correctly uses{ path: "$items" }.Final Answer:
{ $unwind: { path: "$items" } } -> Option BQuick Check:
Use{ path: "$field" }for $unwind [OK]
- Omitting quotes or $ in field path
- Using string without path key
- Passing field name without $ prefix
{ "_id": 1, "tags": ["red", "blue"] }{ "_id": 2, "tags": ["green"] }What will be the output documents after applying this pipeline?
[ { $unwind: "$tags" } ]Solution
Step 1: Understand $unwind effect on arrays
$unwind creates one document per array element, duplicating other fields.Step 2: Apply $unwind to each document
Document 1 with tags ["red", "blue"] becomes two documents with tags "red" and "blue". Document 2 with tags ["green"] becomes one document with tag "green".Final Answer:
[{ "_id": 1, "tags": "red" }, { "_id": 1, "tags": "blue" }, { "_id": 2, "tags": "green" }] -> Option DQuick Check:
Each array element becomes a document = A [OK]
- Expecting original array to remain intact
- Missing duplicated documents for multiple array items
- Confusing $unwind with $group
[ { $unwind: "$comments" } ]But some documents have no
comments field or have it as an empty array. What problem occurs and how to fix it?Solution
Step 1: Identify behavior of $unwind on missing or empty arrays
By default, $unwind removes documents where the array field is missing or empty.Step 2: Use preserveNullAndEmptyArrays option to keep those documents
AddingpreserveNullAndEmptyArrays: truekeeps documents without the array or with empty arrays in the output.Final Answer:
Documents without comments are dropped; fix by addingpreserveNullAndEmptyArrays: truein $unwind. -> Option AQuick Check:
Use preserveNullAndEmptyArrays to keep empty/missing arrays [OK]
- Ignoring dropped documents without array
- Assuming $unwind never drops documents
- Confusing syntax errors with missing field issues
orders which is an array of objects:{ "_id": 1, "orders": [{ "item": "apple", "qty": 5 }, { "item": "banana", "qty": 3 }] }You want to create a list of all items ordered with their quantities as separate documents, but also keep documents that have no orders. Which aggregation pipeline correctly does this?
Solution
Step 1: Use $unwind with preserveNullAndEmptyArrays to keep documents without orders
[ { $unwind: { path: "$orders", preserveNullAndEmptyArrays: true } }, { $project: { item: "$orders.item", qty: "$orders.qty" } } ] usespreserveNullAndEmptyArrays: trueto keep documents that have no orders.Step 2: Project only the needed fields from the unwound orders array
The$projectstage extractsitemandqtyfrom each order object.Final Answer:
[ { $unwind: { path: "$orders", preserveNullAndEmptyArrays: true } }, { $project: { item: "$orders.item", qty: "$orders.qty" } } ] -> Option CQuick Check:
Unwind with preserveNullAndEmptyArrays + project fields = D [OK]
- Omitting preserveNullAndEmptyArrays and losing documents
- Projecting fields before unwind causing errors
- Using $match to filter instead of preserveNullAndEmptyArrays
Ready to prove it?
Pass the test and this pattern moves unknown
