10. Transforming Arrays with $map, $filter, and $reduce
Use $map to transform every array element, $filter to retain elements that satisfy a condition, and $reduce to accumulate a result across an array. These expressions can preserve one pipeline document per parent document, unlike $unwind.
Use as to name the current element in $map and $filter; reference it with $$variable. In $reduce, $$value is the accumulated result and $$this is the current element.
Array expressions generally expect array input. $ifNull can turn a missing or null array into an empty array, but it does not convert arbitrary non-array values into arrays.
$map transforms elements, $filter selects elements, and $reduce accumulates a result. Use $unwind when later stages need each element as a separate document.
db.orders.aggregate([
{
$set: {
electronicsItems: {
$filter: {
input: { $ifNull: ["$items", []] },
as: "item",
cond: { $eq: ["$$item.category", "Electronics"] }
}
}
}
},
{
$set: {
electronicsSubtotal: {
$reduce: {
input: "$electronicsItems",
initialValue: 0,
in: { $add: ["$$value", { $multiply: ["$$this.quantity", "$$this.price"] }] }
}
}
}
}
]);- $map transforms elements.
- $filter selects elements.
- $reduce accumulates a value.
- Array expressions can avoid document expansion.
Which operator returns only array elements whose category is Electronics?