Skip to content

Aggregation Fundamentals

$unwind

Turn array elements into documents, preserve or drop empties, and what that does to counts.

IntermediateAbout 6 minutes

$unwind turns each element of an array into its own document, copying the parent fields. That is how you $group by line item — items on orders — instead of by order.

db.orders.aggregate([
  { $unwind: "$items" }
])
One order, two items → two documents
{ userId: ObjectId("…"), amount: 4900, items: { name: "Mechanical Keyboard", quantity: 1, unitPrice: 4500 } }
{ userId: ObjectId("…"), amount: 4900, items: { name: "USB-C Cable", quantity: 2, unitPrice: 200 } }
Parent amount repeats. items is now one object, not an array.
db.orders.aggregate([
  { $unwind: "$items" },
  { $group: { _id: "$items.name", unitsSold: { $sum: "$items.quantity" } } }
])
Units sold per product name

By default, a missing or empty array produces no output — the parent disappears. { path: "$items", preserveNullAndEmptyArrays: true } keeps it, with items: null. $unwind multiplies document count; $match first or you unwind the whole collection. Summing amount after unwind double-counts the order total — sum items.quantity or unwind only when the metric is per line.

Interview question

What does $unwind do?

Think about it first.

Practice

Unwind line items, then group.