-
Type:
New Feature
-
Resolution: Done
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: Aggregation Framework
-
Fully Compatible
-
Query 13 (04/22/16)
-
(copied to CRM)
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Syntax
{
$reduce: {
input: <array>,
initialValue: <expression>,
in: <expression>
}
}
Examples
> db.coll.insert([
{_id: 1, array_field: [1,2,3]}
{_id: 2, array_field: []}
]);
> db.coll.aggregate([{
$project: {
total: {
$reduce: { // Use $reduce to compute the sum.
input: "$array_field",
initialValue: 0,
in: {$add : ["$$value", "$$this"]}
}
}
}
}])
{_id: 1, total: 6}
{_id: 2, total: 0}
// Example 2
> db.coll.insert([
{_id: 1, array_field: [1,2,3]}
{_id: 2, array_field: []}
]);
> db.coll.aggregate([{
$project: {
array_totals: {
$reduce: { // Compute both the sum and the product.
input: "$array_field",
initialValue: {sum: 0, product: 1},
in: {
sum: {$add : ["$$value.sum", "$$this"]},
product: {$multiply: ["$$value.product", "$$this"]}
}
}
}
}
}])
{_id: 1, array_totals: {sum: 6, product: 6}}
{_id: 2, array_totals: {sum: 0, product: 1}}
Notes
- If input is an empty array, the value given to initialResult is returned.
Errors
- If a value from the input expression is anything but a single array value.
- 'input', 'initialResult', and 'in' are required options.
Old Description
We currently have the $map operator to apply an expression to each element in an array and return an array with the applied results.
Along similar lines, it would also be useful to have a $reduce operator to rollup an array into a scalar element using a specified combining function. For example, to return the sum of all array elements.
To illustrate:
Given an input of:
{ _id:1, array_field: [1,2,3] }
{ _id:2, array_field: [] }
We should return:
{ _id:1, array_total: 6 }
{ _id:2, array_total: 0 }
This is currently possible using a relatively expensive $unwind and $group (plus some additionally voodoo to handle unwinding of the empty arrays), but it would be more elegant, and likely more performant, to do something like the following:
db.coll.aggregate(
[
{ $project:
{ array_total:
{
$reduce:
{
$add: "$array_field",
}
}
}
}
]
)
[Note: the above proposed syntax is just for illustrative purposes]
- is depended on by
-
CSHARP-1662 Add $reduce expression operator for rollup of arrays
-
- Closed
-
- is related to
-
DRIVERS-297 Aggregation Framework Support for 3.4
-
- Closed
-
- related to
-
SERVER-15697 Create a string accumulator for aggregation
-
- Backlog
-
-
SERVER-14359 Allow $max, $min, $avg calculations in $project.
-
- Closed
-
-
SERVER-10682 Expose $multiply as both an accumulator and an expression
-
- Backlog
-
-
SERVER-10676 $multiply does not support a reference to an array
-
- Closed
-
-
SERVER-14872 Aggregation pipeline project expression operator to concatenate multiple arrays into one
-
- Closed
-