$reduce
Same idea as reduce in JavaScript: walk the array, carry a running value. In MongoDB that running value is $$value and the current element is $$this, and the syntax is verbose enough that it pays to read it slowly once.
In JavaScript you would write:
array.reduce(...)
Suppose:
{
scores: [10, 20, 30]
}
Calculate:
10 + 20 + 30
{
$project: {
total: {
$reduce: {
input: "$scores",
initialValue: 0,
in: {
$add: [
"$$value",
"$$this"
]
}
}
}
}
}
Conceptually:
scores.reduce(
(value, current) => value + current,
0
)
MongoDB variables:
$$value
→ accumulator
$$this
→ current array element
Example: Order Total Without $unwind
Given:
{
items: [
{
price: 1000,
quantity: 1
},
{
price: 50,
quantity: 2
}
]
}
Calculate order total:
{
$set: {
orderTotal: {
$reduce: {
input: "$items",
initialValue: 0,
in: {
$add: [
"$$value",
{
$multiply: [
"$$this.price",
"$$this.quantity"
]
}
]
}
}
}
}
}
Result:
1000 + (50 × 2)
= 1100
When $reduce Is Actually Useful
Don’t force $reduce everywhere.
Use it when:
You have an array inside one document and need to calculate one value from that array.
Examples:
Calculate order total
Calculate total duration
Calculate combined score
Concatenate array values
Build a custom object
If you need to aggregate across multiple documents, think:
$group
If you need to reduce one array, think:
$reduce
Very important distinction:
Across documents
→ $group
Inside one array
→ $reduce
Try it
db.orders.aggregate([
{
$project: {
itemCount: {
$reduce: {
input: "$items",
initialValue: 0,
in: { $add: ["$$value", "$$this.quantity"] }
}
}
}
},
{ $limit: 5 }
])
$$value is the running total, $$this is the element. Change $add to $max and the same three lines give you the largest quantity in the order instead of the sum.