Skip to content

$unwind

The $unwind stage deconstructs an array field from the input document to output a document for each element.


📌 Syntax

{ "$unwind": "$<arrayField>" }

✅ Base Example – Unwind Items in Order

📥 Input Document

{
  "orderId": 1,
  "items": [
    { "name": "Laptop", "price": 1200 },
    { "name": "Mouse", "price": 50 }
  ]
}

📌 Stage

{ "$unwind": "$items" }

📤 Output Documents

[
  {
    "orderId": 1,
    "items": { "name": "Laptop", "price": 1200 }
  },
  {
    "orderId": 1,
    "items": { "name": "Mouse", "price": 50 }
  }
]

🧱 Deep Nested Example – Unwind, Compute, and Group by Category

📌 Pipeline

[
  { "$unwind": "$items" },
  {
    "$group": {
      "_id": "$items.category",
      "totalSales": { "$sum": "$items.price" },
      "count": { "$sum": 1 }
    }
  },
  { "$sort": { "totalSales": -1 } }
]

📥 Input Document

{
  "orderId": 5,
  "items": [
    { "name": "Laptop", "price": 1000, "category": "Electronics" },
    { "name": "Shoes", "price": 150, "category": "Fashion" },
    { "name": "Monitor", "price": 500, "category": "Electronics" }
  ]
}

📤 Output Documents

[
  { "_id": "Electronics", "totalSales": 1500, "count": 2 },
  { "_id": "Fashion", "totalSales": 150, "count": 1 }
]

âž• Accumulators Used with $unwind + $group

Accumulator Use Case
$sum Count or compute totals
$avg Category-level average price
$min / $max Lowest/highest item per category
$push List all item names per category
$addToSet Unique brands per category

🔧 Common Operators

Operator Use Case
$group Aggregate after unwinding
$project Select item fields
$sort Rank results by totals
$multiply Compute per-item total

🧠 Tips

  • Combine with $group for powerful analytics
  • Preserve empty arrays with:
    json { "$unwind": { "path": "$items", "preserveNullAndEmptyArrays": true } }
  • Works well with deeply nested item structures

  • $group, $bucket, $facet – to summarize arrays
  • $project, $replaceRoot – to restructure