Details
-
New Feature
-
Status: Closed
-
Major - P3
-
Resolution: Fixed
-
None
-
Fully Compatible
-
Query 13 (04/22/16)
-
(copied to CRM)
Description
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]
Attachments
Issue Links
- is depended on by
-
CSHARP-1662 Add $reduce expression operator for rollup of arrays
-
- Closed
-
- is documented by
-
DOCS-8580 Create 3.4 Manual Page for $reduce
-
- 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
-