Definition定义
$reduceApplies an expression to each element in an array and combines them into a single value.将表达式应用于数组中的每个元素,并将它们组合成一个值。$reducehas the following syntax:具有以下语法:{
$reduce: {
input: <array>,
initialValue: <expression>,
in: <expression>
}
}Field字段Type类型Description描述inputarray数组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如果参数解析为nullor refers to a missing field,$reducereturnsnull.null值或引用缺少的字段,$reduce将返回null。If the argument does not resolve to an array or如果参数未解析为数组或nullnor refers to a missing field,$reducereturns an error.null,也未引用缺失的字段,$reduce将返回错误。initialValueexpression表达式The initial cumulative在valueset beforeinis applied to the first element of theinputarray.in之前设置的初始累积value将应用于input数组的第一个元素。inexpression表达式A valid expression that$reduceapplies to each element in theinputarray in left-to-right order. Wrap theinputvalue with$reverseArrayto yield the equivalent of applying the combining expression from right-to-left.$reduce以从左到右的顺序应用于input数组中每个元素的有效表达式。用$reverseArray包裹input值,相当于从右向左应用组合表达式。During evaluation of the在计算inexpression, two variables will be available:in表达式时,有两个变量可用:If如果inputresolves to an empty array,$reducereturnsinitialValue.input解析为空数组,$reduce将返回initialValue。
| "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.events的集合包含概率实验的事件。每个实验可以有多个events,例如滚动模具几次或连续绘制几张卡片(不更换)以达到预期的结果。为了获得实验的总体概率,我们需要将实验中每个事件的概率相乘。
db.events.insertMany( [
{ _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使用$groupto group by theexperimentIdand use$pushto create an array with the probability of each event.$group按experimentId分组,并使用$push创建一个包含每个事件概率的数组。Use使用$reducewith$multiplyto multiply and combine the elements ofprobabilityArrinto a single value and project it.$reduce和$multiply将probabilityArr的元素相乘并组合成一个值,然后进行投影。
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:clothes的集合包含以下文档:
db.clothes.insertMany( [
{ _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.discounts数组,其中包含每个项目的当前可用折扣优惠券。如果每个折扣可以应用于产品一次,我们可以使用$reduce为折扣数组中的每个元素应用以下公式来计算最低价格:(1-siscount)*price。
db.clothes.aggregate(
[
{
$project: {
discountedPrice: {
$reduce: {
input: "$discounts",
initialValue: "$price",
in: { $multiply: [ "$$value", { $subtract: [ 1, "$$this" ] } ] }
}
}
}
}
]
)
The operation returns the following:该操作返回以下内容:
{ _id : ObjectId("57c893067054e6e47674ce01"), discountedPrice : 9 }
{ _id : ObjectId("57c9932b7054e6e47674ce12"), discountedPrice : 24.224999999999998 }
{ _id : ObjectId("57c993457054e6e47674ce13"), discountedPrice : 24.224999999999998 }
{ _id : ObjectId("57c993687054e6e47674ce14"), discountedPrice : 17.5 }
{ _id : ObjectId("57c993837054e6e47674ce15"), discountedPrice : 54 }String Concatenation字符串连接
A collection named 名为people contains the following documents:people的集合包含以下文档:
db.people.insertMany( [
{ _id : 1, name : "Melissa", hobbies : [ "softball", "drawing", "reading" ] },
{ _id : 2, name : "Brad", hobbies : [ "gaming", "skateboarding" ] },
{ _id : 3, name : "Scott", hobbies : [ "basketball", "music", "fishing" ] },
{ _id : 4, name : "Tracey", hobbies : [ "acting", "yoga" ] },
{ _id : 5, name : "Josh", hobbies : [ "programming" ] },
{ _id : 6, name : "Claire" }
] )
The following example reduces the 以下示例将hobbies array of strings into a single string bio:hobbies字符串数组简化为单个字符串bio:
db.people.aggregate(
[
// Filter to return only non-empty arrays
{ $match: { "hobbies": { $gt: [ ] } } },
{
$project: {
name: 1,
bio: {
$reduce: {
input: "$hobbies",
initialValue: "My hobbies include:",
in: {
$concat: [
"$$value",
{
$cond: {
if: { $eq: [ "$$value", "My hobbies include:" ] },
then: " ",
else: ", "
}
},
"$$this"
]
}
}
}
}
}
]
)
The operation returns the following:该操作返回以下内容:
{ _id : 1, name : "Melissa", bio : "My hobbies include: softball, drawing, reading" }
{ _id : 2, name : "Brad", bio : "My hobbies include: gaming, skateboarding" }
{ _id : 3, name : "Scott", bio : "My hobbies include: basketball, music, fishing" }
{ _id : 4, name : "Tracey", bio : "My hobbies include: acting, yoga" }
{ _id : 5, name : "Josh", bio : "My hobbies include: programming" }Array Concatenation数组连接
A collection named 名为matrices contains the following documents:matrices的集合包含以下文档:
db.matrices.insertMany( [
{ _id : 1, arr : [ [ 24, 55, 79 ], [ 14, 78, 35 ], [ 84, 90, 3 ], [ 50, 89, 70 ] ] },
{ _id : 2, arr : [ [ 39, 32, 43, 7 ], [ 62, 17, 80, 64 ], [ 17, 88, 11, 73 ] ] },
{ _id : 3, arr : [ [ 42 ], [ 26, 59 ], [ 17 ], [ 72, 19, 35 ] ] },
{ _id : 4 }
] )
Computing a Single Reduction计算单个缩减
The following example collapses the two dimensional arrays into a single array 以下示例将二维数组折叠为单个数组collapsed:collapsed:
db.arrayconcat.aggregate(
[
{
$project: {
collapsed: {
$reduce: {
input: "$arr",
initialValue: [ ],
in: { $concatArrays: [ "$$value", "$$this" ] }
}
}
}
}
]
)
The operation returns the following:该操作返回以下内容:
{ _id : 1, collapsed : [ 24, 55, 79, 14, 78, 35, 84, 90, 3, 50, 89, 70 ] }
{ _id : 2, collapsed : [ 39, 32, 43, 7, 62, 17, 80, 64, 17, 88, 11, 73 ] }
{ _id : 3, collapsed : [ 42, 26, 59, 17, 72, 19, 35 ] }
{ _id : 4, collapsed : null }Computing a Multiple Reductions计算多重折减
The following example performs the same two dimensional array collapse as the example above, but also creates a new array containing only the first element of each array.以下示例执行与上述示例相同的二维数组折叠,但也创建了一个仅包含每个数组第一个元素的新数组。
db.arrayconcat.aggregate(
[
{
$project: {
results: {
$reduce: {
input: "$arr",
initialValue: [ ],
in: {
collapsed: {
$concatArrays: [ "$$value.collapsed", "$$this" ]
},
firstValues: {
$concatArrays: [ "$$value.firstValues", { $slice: [ "$$this", 1 ] } ]
}
}
}
}
}
}
]
)
The operation returns the following:该操作返回以下内容:
{ _id : 1, results : { collapsed : [ 24, 55, 79, 14, 78, 35, 84, 90, 3, 50, 89, 70 ], firstValues : [ 24, 14, 84, 50 ] } }
{ _id : 2, results : { collapsed : [ 39, 32, 43, 7, 62, 17, 80, 64, 17, 88, 11, 73 ], firstValues : [ 39, 62, 17 ] } }
{ _id : 3, results : { collapsed : [ 42, 26, 59, 17, 72, 19, 35 ], firstValues : [ 42, 26, 17, 72 ] } }
{ _id : 4, results : null }