Skip to content

Aggregation Expressions

Array Expressions

$size, $filter, $map and $reduce — transforming arrays without leaving the document.

AdvancedAbout 8 minutes

$unwind explodes an array into documents. Array expressions reshape the array in place. Use unwind when the next $group is across orders. Use $map / $filter / $reduce when the answer still belongs on this order.

db.orders.aggregate([
  {
    $set: {
      bulky: {
        $filter: {
          input: "$items",
          as: "line",
          cond: { $gt: ["$$line.quantity", 1] }
        }
      },
      items: {
        $map: {
          input: "$items",
          as: "line",
          in: {
            name: "$$line.name",
            quantity: "$$line.quantity",
            unitPrice: "$$line.unitPrice",
            lineTotal: { $multiply: ["$$line.quantity", "$$line.unitPrice"] }
          }
        }
      }
    }
  }
])
$filter and $map — keep some lines, add a line total

$$line is the variable from as. Omit as and the name is $$this. $ paths are still the parent document ($items). Mixing $line (a field named line on the order) with $$line is the usual bug.

{
  $reduce: {
    input: "$items",
    initialValue: 0,
    in: {
      $add: [
        "$$value",
        { $multiply: ["$$this.quantity", "$$this.unitPrice"] }
      ]
    }
  }
}
$reduce — order total from lines, no unwind
OperatorUse
$sizeLength; [] is 0
$filterKeep elements that match cond
$mapOne output element per input element
$reduceFold to one value; $$value is the accumulator, $$this the element
$arrayElemAt / $first / $lastOne element by index or ends
$inExpression form: { $in: ["MongoDB", "$skills"] }

$size on a missing field errors — $ifNull: ["$items", []] first. Set operators ($setUnion, $setIntersection) exist for tag arrays; you do not need them until you are merging two lists. Units sold across the collection is still $unwind then $group (most-purchased-products). $map cannot see other orders.

Interview question

When do you use $map / $filter instead of $unwind?

Think about it first.