Aggregation Fundamentals
$unwind
Turn array elements into documents, preserve or drop empties, and what that does to counts.
$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" }
]){ 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 } }db.orders.aggregate([
{ $unwind: "$items" },
{ $group: { _id: "$items.name", unitsSold: { $sum: "$items.quantity" } } }
])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?
Each array element becomes its own document; parent fields are copied. That is how you group or total per line item. Empty arrays drop the parent unless preserveNullAndEmptyArrays is true. Unwind multiplies rows, so $match first.
Practice
Unwind line items, then group.