Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

$reduce(式 演算子)

$reduce

配列内の各要素に式を適用し、それらを 1 つの値に結合します。

$reduce の構文は次のとおりです。

{
$reduce: {
input: <array>,
initialValue: <expression>,
in: <expression>,
as: <string>,
valueAs: <string>,
arrayIndexAs: <string>
}
}
フィールド
タイプ
説明

input

配列

配列に変換される有効なであればどれでもかまいません。 式の詳細については、「式 」を参照してください。

引数がnull の値に解決されるか、欠落しているフィールドを参照する場合、$reduce nullは を返します。

引数が配列またはnull に解決されず、欠落しているフィールドを参照しない場合は、$reduce はエラーを返します。

initialValue

in の前に設定された最初の推計 value は、input 配列の最初の要素に適用されます。

in

input 配列で、左から右へそれぞれの要素に $reduce を適用する有効なinput 値を $reverseArrayでラップすると、結合式を右から左に適用するのと同じ結果が得られます。

in 式の評価では 2 つの変数が利用可能です。

  • value は式の累積値を表す変数です。

  • this は処理対象の要素を参照する変数です。

as

string

任意。 input 配列の各要素を表す 変数 の名前。省略した場合、変数名はデフォルトで this になります。

バージョン8.3の新機能

valueAs

string

任意。式の累積値を表す 変数 の名前。省略した場合、変数名はデフォルトで value になります。

バージョン8.3の新機能

arrayIndexAs

string

任意。 input配列内の現在の要素のインデックスを表す集計変数の名前。最初の配列要素インデックスは0 です。

変数名は式で使用できます。例、arrayIndexAs: "myIndex" を指定した場合、式では $$myIndex が使用されます。 $$myIndex は、input 配列内の現在の要素のインデックスを返します。

arrayIndexAs$$IDXを省略する場合は、式で システム変数を使用して現在の要素のインデックスを返すことができます。

例については、「 配列内の各アイテムのインデックスにアクセスする 」と「 $$IDXを使用してインデックスにアクセスする 」を参照してください。

バージョン8.3の新機能

input が空の配列に解決された場合、$reduceinitialValue を返します。

結果
{
$reduce: {
input: ["a", "b", "c"],
initialValue: "",
in: { $concat : ["$$value", "$$this"] }
}
}

"abc"

{
$reduce: {
input: [ 1, 2, 3, 4 ],
initialValue: { sum: 5, product: 2 },
in: {
sum: { $add : ["$$value.sum", "$$this"] },
product: { $multiply: [ "$$value.product", "$$this" ] }
}
}
}

{ "sum" : 15, "product" : 48 }

{
$reduce: {
input: [ [ 3, 4 ], [ 5, 6 ] ],
initialValue: [ 1, 2 ],
in: { $concatArrays : ["$$value", "$$this"] }
}
}

[ 1, 2, 3, 4, 5, 6 ]

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 }
] )

手順:

  1. $group を使用して experimentId でグループ化し、$push を使用して各イベントの確率を含む配列を作成します。

  2. $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 }

これらのドキュメントを使用して、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フィールドには、各人の趣味の配列がランク付けされています。配列の最初の趣味は、人が最も多くの時間を費やしたその人のプライマリ趣味です。最初の趣味の配列インデックスは 0 です。

次の例では、valueAsasarrayIndexAs を使用します。 myIndex 変数には、hobbies 配列内の各趣味のインデックスがあります。この例では、次のフィールドを持つドキュメントが返されます。

  • 人の名前。

  • text フィールド には、趣味の名前とリスト内の各趣味の位置が含まれます。

db.people.aggregate( [
{
$project: {
_id: 0,
name: 1,
text: {
$reduce: {
input: "$hobbies",
initialValue: "My hobbies include:",
valueAs: "accumulatedText",
as: "hobby",
arrayIndexAs: "myIndex",
in: {
$concat: [
"$$accumulatedText",
" ",
{ $toString: { $add: [ "$$myIndex", 1 ] } },
") ",
"$$hobby"
]
}
}
}
}
}
] )

出力:

[
{ "name" : "Melissa", "text" : "My hobbies include: 1) softball 2) drawing 3) reading" }
{ "name" : "Brad", "text" : "My hobbies include: 1) gaming 2) skateboarding" }
{ "name" : "Scott", "text" : "My hobbies include: 1) basketball 2) music 3) fishing" }
{ "name" : "Tracey", "text" : "My hobbies include: 1) acting 2) yoga" }
{ "name" : "Josh", "text" : "My hobbies include: 1) programming" }
{ "name" : "Claire", "text" : null }
]

$$IDX変数は、input 配列内の現在の要素のインデックスを返します。式から$$IDX arrayIndexAsフィールドを省略すると、 を使用できます。

次の例では、前のセクションの例と同じドキュメントが返されます。ただし、 $$IDXではなくarrayIndexAs が使用されています。

db.people.aggregate( [
{
$project: {
_id: 0,
name: 1,
text: {
$reduce: {
input: "$hobbies",
initialValue: "My hobbies include:",
valueAs: "accumulatedText",
as: "hobby",
in: {
$concat: [
"$$accumulatedText",
" ",
{ $toString: { $add: [ "$$IDX", 1 ] } },
") ",
"$$hobby"
]
}
}
}
}
}
] )

戻る

$rank

項目一覧