querydrill

Learn ›Aggregation ›Arrays in a pipeline

$unwind

$unwind flattens an array into separate documents - one per element, each carrying a copy of the parent fields. Once you can picture that output, the rest of aggregation over arrays follows.

Input:

{
  _id: 1,

  userId: 101,

  items: [
    {
      product: "Laptop",
      price: 1000,
      quantity: 1
    },
    {
      product: "Mouse",
      price: 50,
      quantity: 2
    }
  ]
}

Pipeline:

{
  $unwind: "$items"
}

Output:

{
  _id: 1,
  userId: 101,

  items: {
    product: "Laptop",
    price: 1000,
    quantity: 1
  }
}

AND:

{
  _id: 1,
  userId: 101,

  items: {
    product: "Mouse",
    price: 50,
    quantity: 2
  }
}

One document became two documents.

This is the key idea:

Before $unwind

Order
 ├── Laptop
 └── Mouse

After $unwind

Order + Laptop

Order + Mouse

Try it

Order 1 in the sample data has four items:

db.orders.aggregate([
  { $match: { _id: 1 } },
  { $unwind: "$items" }
])

Four documents came out, each carrying the same _id, userId and status - and one item. Change the _id and the number of output documents follows the array length.