![]() |
VOOZH | about |
The $unwind operator in MongoDB breaks down an array field into multiple documents, where each document contains one element from the original array. The array field is replaced with one element from the array for each new document.
Syntax:
{
$unwind: <field path>
}
To understand How to Use $unwind Operator in MongoDB collection we need a collection and some documents on which we will perform various operations and queries.
employees [
{
"_id": ObjectId("..."),
"name": "Mikky",
"age": 31,
"phone_no": 8654793212,
"company": "javatpoint",
"skills": ["C", "C++", "PHP", "Java", ".Net"]
},
{
"_id": ObjectId("..."),
"name": "John",
"age": 28,
"phone_no": 1234567890,
"company": "techguy",
"skills": ["JavaScript", "Python", "Go"]
},
{
"_id": ObjectId("..."),
"name": "Alice",
"age": 26,
"phone_no": 9876543210,
"company": "webmasters",
"skills": []
},
{
"_id": ObjectId("..."),
"name": "David",
"age": 40,
"phone_no": 5647382910,
"company": "devteam",
"skills": ["Ruby", "PHP", "Node.js"]
}
]
When working with array fields, the $unwind operator helps convert each array element into a separate document. This makes it easier to query, filter, and analyze individual elements within the array. Let's use the $unwind operator to break down the skills array into individual documents.
Query:
db.employee.aggregate([
{
$unwind: "$skills"
}
]);
Output:
{
"_id": ObjectId("..."),
"name": "Mikky",
"age": 31,
"phone_no": 8654793212,
"company": "javatpoint",
"skills": "C"
}
{
"_id": ObjectId("..."),
"name": "Mikky",
"age": 31,
"phone_no": 8654793212,
"company": "javatpoint",
"skills": "C++"
}
{
"_id": ObjectId("..."),
"name": "Mikky",
"age": 31,
"phone_no": 8654793212,
"company": "javatpoint",
"skills": "PHP"
}
{
"_id": ObjectId("..."),
"name": "Mikky",
"age": 31,
"phone_no": 8654793212,
"company": "javatpoint",
"skills": "Java"
}
{
"_id": ObjectId("..."),
"name": "Mikky",
"age": 31,
"phone_no": 8654793212,
"company": "javatpoint",
"skills": ".Net"
}
{
"_id": ObjectId("..."),
"name": "John",
"age": 28,
"phone_no": 1234567890,
"company": "techguy",
"skills": "JavaScript"
}
{
"_id": ObjectId("..."),
"name": "John",
"age": 28,
"phone_no": 1234567890,
"company": "techguy",
"skills": "Python"
}
{
"_id": ObjectId("..."),
"name": "John",
"age": 28,
"phone_no": 1234567890,
"company": "techguy",
"skills": "Go"
}
{
"_id": ObjectId("..."),
"name": "David",
"age": 40,
"phone_no": 5647382910,
"company": "devteam",
"skills": "Ruby"
}
{
"_id": ObjectId("..."),
"name": "David",
"age": 40,
"phone_no": 5647382910,
"company": "devteam",
"skills": "PHP"
}
{
"_id": ObjectId("..."),
"name": "David",
"age": 40,
"phone_no": 5647382910,
"company": "devteam",
"skills": "Node.js"
}
Explanation:
skills entry is now an individual document.Alice) are omitted from the resultsIn many cases, documents contain nested arrays within objects, making it necessary to extract and analyze individual elements. The $unwind operator can be applied to embedded arrays, breaking them down into separate documents while preserving other fields.
Next, let’s create a new collection called products and populate it with some documents that include embedded arrays. We'll then apply $unwind to deconstruct these arrays for better queryability.
products[
{
"_id": "1",
"items": [
{
"name": "copy",
"work": ["write", "office"],
"cost": 10,
"total_quantity": 5
},
{
"name": "pencil",
"work": ["write", "school"],
"cost": 2,
"total_quantity": 5
}
]
},
{
"_id": "2",
"items": [
{
"name": "monitor",
"work": ["college", "office"],
"cost": 5000,
"total_quantity": 1
},
{
"name": "mouse",
"work": ["laptop", "CPU"],
"cost": 300,
"total_quantity": 5
}
]
}
]
items arraydb.products.aggregate([
{
$unwind: "$items"
}
]);
Output:
{
"_id": "1",
"items": {
"name": "copy",
"work": ["write", "office"],
"cost": 10,
"total_quantity": 5
}
}
{
"_id": "1",
"items": {
"name": "pencil",
"work": ["write", "school"],
"cost": 2,
"total_quantity": 5
}
}
{
"_id": "2",
"items": {
"name": "monitor",
"work": ["college", "office"],
"cost": 5000,
"total_quantity": 1
}
}
{
"_id": "2",
"items": {
"name": "mouse",
"work": ["laptop", "CPU"],
"cost": 300,
"total_quantity": 5
}
}
Explanation:
The $unwind stage normally splits array fields into multiple documents.
Example:
Collection students:
{ "_id": 1, "name": "Alice", "scores": 90 }
{ "_id": 2, "name": "Bob", "scores": [85, 88] }
{ "_id": 3, "name": "Charlie" }
Aggregation:
db.students.aggregate([
{ $unwind: "$scores" }
])
Output:
{ "_id" : 1, "name" : "Alice", "scores" : 90 }
{ "_id" : 2, "name" : "Bob", "scores" : 85 }
{ "_id" : 2, "name" : "Bob", "scores" : 88 }
Explanation:
The preserveNullAndEmptyArrays option ensures that documents with missing or null fields are kept in the output when using $unwind.
Example:
{ "_id": 1, "name": "Alice", "scores": 90 }
{ "_id": 2, "name": "Bob", "scores": [85, 88] }
{ "_id": 3, "name": "Charlie" }
Aggregation:
db.students.aggregate([
{ $unwind: { path: "$scores", preserveNullAndEmptyArrays: true } }
])
Output:
{ "_id" : 1, "name" : "Alice", "scores" : 90 }
{ "_id" : 2, "name" : "Bob", "scores" : 85 }
{ "_id" : 2, "name" : "Bob", "scores" : 88 }
Explanation:
The $unwind operator splits array fields into separate documents. The includeArrayIndex option adds a new field that stores the index position of each element in the original array. This helps in grouping or ordering elements based on their position.
Example:
{ "_id": 1, "name": "Alice", "scores": [90, 85, 88] }Query:
db.students.aggregate([
{ $unwind: { path: "$scores", includeArrayIndex: "scoreIndex" } }
])
Output:
{ "_id" : 1, "name" : "Alice", "scores" : 90, "scoreIndex" : 0 }
{ "_id" : 1, "name" : "Alice", "scores" : 85, "scoreIndex" : 1 }
{ "_id" : 1, "name" : "Alice", "scores" : 88, "scoreIndex" : 2 }
Explanation: