On this page
$reduce (aggregation)
On this page
Definition
$reduce
-
New in version 3.4.
Applies an expression to each element in an array and combines them into a single value.
$reduce
has the following syntax:{ $reduce: { input: <array>, initialValue: <expression>, in: <expression> } }
Field Type Description input
array Can be any valid expression that resolves to an array. For more information on expressions, see Expressions.
If the argument resolves to a value of
null
or refers to a missing field,$reduce
returnsnull
.If the argument does not resolve to an array or
null
nor refers to a missing field,$reduce
returns an error.initialValue
expression The initial cumulative value
set beforein
is applied to the first element of theinput
array.in
expression A valid expression that
$reduce
applies to each element in theinput
array in left-to-right order. Wrap theinput
value with$reverseArray
to yield the equivalent of applying the combining expression from right-to-left.During evaluation of the
in
expression, two variables will be available:If
input
resolves to an empty array,$reduce
returnsinitialValue
.
Example | Results |
---|---|
|
"abc" |
|
{ "sum" : 15, "product" : 48 } |
|
[ 1, 2, 3, 4, 5, 6 ] |
Examples
Multiplication
Probability
A collection named events
contains the events of a probability experiment. Each experiment can have multiple events
, such as rolling a die several times or drawing several cards (without replacement) in succession to achieve a desired result. In order to obtain the overall probability of the experiment, we will need to multiply the probability of each event in the experiment.
{_id:1, "type":"die", "experimentId":"r5", "description":"Roll a 5", "eventNum":1, "probability":0.16666666666667}
{_id:2, "type":"card", "experimentId":"d3rc", "description":"Draw 3 red cards", "eventNum":1, "probability":0.5}
{_id:3, "type":"card", "experimentId":"d3rc", "description":"Draw 3 red cards", "eventNum":2, "probability":0.49019607843137}
{_id:4, "type":"card", "experimentId":"d3rc", "description":"Draw 3 red cards", "eventNum":3, "probability":0.48}
{_id:5, "type":"die", "experimentId":"r16", "description":"Roll a 1 then a 6", "eventNum":1, "probability":0.16666666666667}
{_id:6, "type":"die", "experimentId":"r16", "description":"Roll a 1 then a 6", "eventNum":2, "probability":0.16666666666667}
{_id:7, "type":"card", "experimentId":"dak", "description":"Draw an ace, then a king", "eventNum":1, "probability":0.07692307692308}
{_id:8, "type":"card", "experimentId":"dak", "description":"Draw an ace, then a king", "eventNum":2, "probability":0.07843137254902}
Steps:
- Use
$group
to group by theexperimentId
and use$push
to create an array with the probability of each event. - Use
$reduce
with$multiply
to multiply and combine the elements ofprobabilityArr
into a single value and project it.
db.probability.aggregate(
[
{
$group: {
_id: "$experimentId",
"probabilityArr": { $push: "$probability" }
}
},
{
$project: {
"description": 1,
"results": {
$reduce: {
input: "$probabilityArr",
initialValue: 1,
in: { $multiply: [ "$$value", "$$this" ] }
}
}
}
}
]
)
The operation returns the following:
{ "_id" : "dak", "results" : 0.00603318250377101 }
{ "_id" : "r5", "results" : 0.16666666666667 }
{ "_id" : "r16", "results" : 0.027777777777778886 }
{ "_id" : "d3rc", "results" : 0.11764705882352879 }
Discounted Merchandise
A collection named clothes
contains the following documents:
{ "_id" : 1, "productId" : "ts1", "description" : "T-Shirt", "color" : "black", "size" : "M", "price" : 20, "discounts" : [ 0.5, 0.1 ] }
{ "_id" : 2, "productId" : "j1", "description" : "Jeans", "color" : "blue", "size" : "36", "price" : 40, "discounts" : [ 0.25, 0.15, 0.05 ] }
{ "_id" : 3, "productId" : "s1", "description" : "Shorts", "color" : "beige", "size" : "32", "price" : 30, "discounts" : [ 0.15, 0.05 ] }
{ "_id" : 4, "productId" : "ts2", "description" : "Cool T-Shirt", "color" : "White", "size" : "L", "price" : 25, "discounts" : [ 0.3 ] }
{ "_id" : 5, "productId" : "j2", "description" : "Designer Jeans", "color" : "blue", "size" : "30", "price" : 80, "discounts" : [ 0.1, 0.25 ] }
Each document contains a discounts
array containing the currently available percent-off coupons for each item. If each discount can be applied to the product once, we can calculate the lowest price by using $reduce
to apply the following formula for each element in the discounts
array: (1 - discount) * price.
db.clothes.aggregate(
[
{
$project: {
"discountedPrice": {
$reduce: {
input: "$discounts",
initialValue: "$price",
in: { $multiply: [ "$$value", { $subtract: [ 1, "$$this" ] } ] }
}
}
}
}
]
)
The operation returns the following: