$unwind helps to take a list inside a document and make each item in that list its own document. This makes it easier to work with each item separately.
$unwind for flattening arrays in MongoDB
db.collection.aggregate([
{ $unwind: "$arrayField" }
])Replace collection with your collection name.
Replace arrayField with the name of the array you want to flatten.
db.people.aggregate([
{ $unwind: "$hobbies" }
])db.orders.aggregate([
{ $unwind: "$items" }
])db.products.aggregate([
{ $unwind: "$tags" }
])db.products.aggregate([
{ $unwind: { path: "$tags", preserveNullAndEmptyArrays: true } }
])This example inserts four people. Some have hobbies, some have empty or missing hobbies. The $unwind stage flattens hobbies so each hobby is a separate document. The option preserveNullAndEmptyArrays: true keeps people with no hobbies in the result.
db.people.insertMany([
{ _id: 1, name: "Alice", hobbies: ["reading", "swimming"] },
{ _id: 2, name: "Bob", hobbies: ["cycling"] },
{ _id: 3, name: "Carol", hobbies: [] },
{ _id: 4, name: "Dave" }
])
// Use $unwind to flatten hobbies
const result = db.people.aggregate([
{ $unwind: { path: "$hobbies", preserveNullAndEmptyArrays: true } }
]).toArray()
printjson(result)Time complexity depends on the number of documents and the size of the arrays inside them.
Space complexity increases because one document with an array becomes many documents.
A common mistake is forgetting preserveNullAndEmptyArrays and losing documents with empty or missing arrays.
Use $unwind when you want to work with each array item separately. If you want to keep arrays as they are, do not use $unwind.
$unwind turns each item in an array into its own document.
It helps to analyze or filter array items easily.
Remember to use preserveNullAndEmptyArrays if you want to keep documents without array items.
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
