$reduce(集計)
定義
$reduce
配列内の各要素に式を適用し、それらを 1 つの値に結合します。
$reduce
の構文は次のとおりです。{ $reduce: { input: <array>, initialValue: <expression>, in: <expression> } } フィールドタイプ説明input
配列
配列に変換される有効な式であればどれでもかまいません。 式の詳細については、「式 」を参照してください。
引数が
null
の値に解決されるか、欠落しているフィールドを参照する場合、$reduce
null
は を返します。引数が配列または
null
に解決されず、欠落しているフィールドを参照しない場合は、$reduce
はエラーを返します。initialValue
式
in
の前に設定された最初の推計value
は、input
配列の最初の要素に適用されます。in
式
input
配列で、左から右へそれぞれの要素に$reduce
を適用する有効な式。input
値を$reverseArray
でラップすると、結合式を右から左に適用するのと同じ結果が得られます。in
式の評価では 2 つの変数が利用可能です。input
が空の配列に解決された場合、$reduce
はinitialValue
を返します。
例 | 結果 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
| ||||||||||
|
| ||||||||||
|
|
例
乗算
確率
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 } ] )
手順:
$group
を使用してexperimentId
でグループ化し、$push
を使用して各イベントの確率を含む配列を作成します。$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" ] } } } } } ] )
この操作では、以下を返します。
{ _id : "dak", results : 0.00603318250377101 } { _id : "r5", results : 0.16666666666667 } { _id : "r16", results : 0.027777777777778886 } { _id : "d3rc", results : 0.11764705882352879 }
割引商品
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 ] } ] )
各ドキュメントには、各商品で現在利用可能な割引クーポンを含む discounts
配列が含まれています。各割引率を製品に 1 回適用できる場合は、$reduce
を使用して discounts
配列の各要素に (1-割引率) * 価格の式を適用することで、最低価格を計算できます。
db.clothes.aggregate( [ { $project: { discountedPrice: { $reduce: { input: "$discounts", initialValue: "$price", in: { $multiply: [ "$$value", { $subtract: [ 1, "$$this" ] } ] } } } } } ] )
この操作では、以下を返します。
{ _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 }
文字列の連結
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" } ] )
次の例では、文字列の配列 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" ] } } } } } ] )
この操作では、以下を返します。
{ _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" }
配列の連結
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 } ] )
単一の削減の計算
次の例では、2 次元配列を 1 つの配列 collapsed
に折りたたみます。
db.arrayconcat.aggregate( [ { $project: { collapsed: { $reduce: { input: "$arr", initialValue: [ ], in: { $concatArrays: [ "$$value", "$$this" ] } } } } } ] )
この操作では、以下を返します。
{ _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 }
多重削減の計算
次の例では、上の例と同じ 2 次元配列の削減を実行しますが、各配列の最初の要素のみを含む新しい配列も作成します。
db.arrayconcat.aggregate( [ { $project: { results: { $reduce: { input: "$arr", initialValue: [ ], in: { collapsed: { $concatArrays: [ "$$value.collapsed", "$$this" ] }, firstValues: { $concatArrays: [ "$$value.firstValues", { $slice: [ "$$this", 1 ] } ] } } } } } } ] )
この操作では、以下を返します。
{ _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 }