注意
map-reduce の代替としての集計パイプライン
MongoDB 5.0以降、 map-reduceは非推奨です。
- map-reduceの代わりに、集計パイプラインを使用する必要があります。 集計パイプラインは、map-reduce よりもパフォーマンスとユーザビリティが優れています。 
- $group- $mergeなどの集約パイプライン ステージ を使用して、map-reduce操作を書き換えることができます。
- カスタム機能を必要とする map-reduce 操作には、 - $accumulatorと- $functionの集計演算子を使用できます。 これらの演算子を使用して、JavaScript でカスタム集計式を定義できます。
map-reduce を集計パイプラインに置き換える例については、以下を参照してください。
- db.collection.mapReduce(map,reduce, { <options> })
- 重要- mongosh メソッド- このページでは、 - mongoshメソッドについて記載しています。ただし、データベースコマンドや Node.js などの言語固有のドライバーのドキュメントには該当しません。- データベースコマンドについては、 - mapReduceコマンドを参照してください。- MongoDB API ドライバーについては、各言語の MongoDB ドライバー ドキュメントを参照してください。 - 注意- ビューでは map-reduce 操作をサポートしていません。 
互換性
このメソッドは、次の環境でホストされている配置で使用できます。
- MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです 
重要
このコマンドは、M 0 、M 2 、M 5クラスターではサポートされていません。 詳細については、「サポートされていないコマンド 」を参照してください。
- MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン 
- MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン 
構文
注意
db.collection.mapReduce()  の構文は次のとおりです。
db.collection.mapReduce(                          <map>,                          <reduce>,                          {                            out: <collection>,                            query: <document>,                            sort: <document>,                            limit: <number>,                            finalize: <function>,                            scope: <document>,                            jsMode: <boolean>,                            verbose: <boolean>,                            bypassDocumentValidation: <boolean>                          }                        ) 
db.collection.mapReduce()  は以下のパラメーターを取ります。
| Parameter | タイプ | 説明 | 
|---|---|---|
| 
 | javascript または文字列 | 
 詳細については、 map 関数の要件 を参照してください。 | 
| 
 | javascript または文字列 | 特定の 詳細については、「 reduce 関数の要件 」を参照してください。 | 
| 
 | ドキュメント | 
次の表では、db.collection.mapReduce() が受け入れることができる追加の引数について説明します。
| フィールド | タイプ | 説明 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 
 | 文字列またはドキュメント | |||||||||||
| 
 | ドキュメント | 
 | ||||||||||
| 
 | ドキュメント | 入力ドキュメントを並べ替えます。このオプションは、最適化に役立ちます。たとえば、sort キーを emit キーと同じものに指定すると、reduce 操作の数を減らせます。sort キーは、このコレクションの既存のインデックス内になければなりません。 | ||||||||||
| 
 | 数値 | 
 | ||||||||||
| 
 | javascript または文字列 | 任意。  詳細については、 finalize 関数の要件を参照してください。 | ||||||||||
| 
 | ドキュメント | 
 | ||||||||||
| 
 | ブール値 | 
 デフォルトは  
 
 
 
 | ||||||||||
| 
 | ブール値 | 結果情報に  デフォルトは  このオプションは無視されます。 結果情報には常に  | ||||||||||
| 
 | ドキュメント | 任意。 操作に使用する照合を指定します。 照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。 照合オプションの構文は次のとおりです。 照合を指定する場合、 照合が指定されていなくても、コレクションにデフォルトの照合が設定されている場合( コレクションにも操作にも照合が指定されていない場合、MongoDB では以前のバージョンで使用されていた単純なバイナリ比較によって文字列が比較されます。 1 つの操作に複数の照合は指定できません。たとえば、フィールドごとに異なる照合を指定できません。また、ソートと検索を一度に実行する場合、検索とソートで別の照合を使用できません。 バージョン 3.4 で追加。 | ||||||||||
| 
 | ブール値 | 任意。 バージョン 3.2 で追加。 | 
注意
map-reduce operations および $where 演算子式は、mongosh 内で使用可能な db などの特定のグローバル関数またはプロパティにアクセスできません 。
次の JavaScript 関数とプロパティは、map-reduce operationsおよび$where 演算子の式で使用できます。
| 利用可能なプロパティ | 利用可能な機能 | |
|---|---|---|
| argsMaxKeyMinKey | assert()BinData()DBPointer()DBRef()doassert()emit()gc()HexData()hex_md5()isNumber()isObject()ISODate()isString() | Map()MD5()NumberInt()NumberLong()ObjectId()print()printjson()printjsononeline()sleep()Timestamp()tojson()tojsononeline()tojsonObject()UUID()version() | 
map関数の要件
map関数は、各入力ドキュメントを 0 個以上のドキュメントに変換するのを担当します。 scopeパラメータで定義された変数にアクセスでき、次のプロトタイプがあります。
function() {    ...    emit(key, value); } 
map関数には次の要件があります。
- map関数は、関数内で現在のドキュメントを- thisとして参照します。
- map関数は、何らかの理由で データベースにアクセスしてはなりません。
- map関数は純粋で、関数の外部に影響を与えないようにする必要があります( 副作用はありません。)
- map関数は任意に、任意の回数で- emit(key,value)を呼び出して、- keyを- valueに関連付ける出力ドキュメントを作成できます。
次のmap関数は、入力ドキュメントのstatusフィールドの値に応じてemit(key,value)を 0 回または 1 回呼び出します。
function() {     if (this.status == 'A')         emit(this.cust_id, 1); } 
次のmap関数は、入力ドキュメントのitemsフィールドの要素数に応じて、 emit(key,value)を複数回呼び出す場合があります。
function() {     this.items.forEach(function(item){ emit(item.sku, 1); }); } 
reduce関数の要件
reduce関数のプロトタイプは次のとおりです。
function(key, values) {    ...    return result; } 
reduce関数は、次の動作を示します。
- reduce関数は、読み取り操作を実行する場合でも、データベースにアクセスしないでください。
- reduce関数は外部システムに影響を与えないようにする必要があります。
- MongoDB では、同じキーに対して - reduce関数を複数回呼び出すことができます。 この場合、そのキーの- reduce関数からの前回の出力は、そのキーの次の- reduce関数を呼び出すへの入力値の 1 つになります。
- reduce関数は、- scopeパラメータで定義された変数にアクセスできます。
- reduceへの入力は、MongoDB の最大 BSON ドキュメント サイズの半分を超えてはなりません。 この要件は、大きなドキュメントが返され、後続の- reduceステップで結合された場合に違反される可能性があります。
同じキーに対してreduce関数を複数回呼び出すことができるため、次のプロパティが true である必要があります。
- 返されるオブジェクトの型は、 - map関数によって出力される- valueの型と同一である必要があります。
- reduce関数は連想である必要があります。 次のステートメントは true である必要があります。- reduce(key, [ C, reduce(key, [ A, B ]) ] ) == reduce( key, [ C, A, B ] ) 
- reduce関数は冪等である必要があります。 次の文が true であることを確認します。- reduce( key, [ reduce(key, valuesArray) ] ) == reduce( key, valuesArray ) 
- reduce関数はメンバーシップである必要があります 。つまり、- valuesArray内の要素の順序は- reduce関数の出力に影響を与えず、次のステートメントが当てはまります。- reduce( key, [ A, B ] ) == reduce( key, [ B, A ] ) 
out オプション
outパラメータには次のオプションを指定できます。
コレクションへの出力
このオプションは新しいコレクションに出力し、レプリカセットのセカンダリ ノードでは使用できません。
out: <collectionName> 
アクションを使用したコレクションへの出力
注意
MongoDB バージョン 4.2 以降、次の機能が廃止されます。
- 新しいシャーディングされたコレクションを作成するための map-reduce オプション、および、map-reduce のシャードオプションの使用。シャーディングされたコレクションに出力するには、まずシャーディングされたコレクションを作成します。MongoDB 4.2 では、既存のシャーディングされたコレクションの置き換えも非推奨となります。ん。 
このオプションは、すでに存在するコレクションをoutに渡す場合にのみ使用できます。 レプリカセットの セカンダリ ノードでは使用できません。
out: { <action>: <collectionName>         [, db: <dbName>]         [, sharded: <boolean> ] } 
アクションを使用してコレクションに出力する場合、 outには次のパラメータがあります。
- <action>: 次のいずれかのアクションを指定します。- replace- <collectionName>のコレクションが存在する場合は、- <collectionName>の内容を置き換えます。
- merge- 出力コレクションがすでに存在する場合は、新しい結果を既存の結果とマージします。 既存のドキュメントが新しい結果と同じキーを持っている場合は、その既存のドキュメントを上書きします。 
- reduce- 出力コレクションがすでに存在する場合は、新しい結果を既存の結果とマージします。 既存のドキュメントが新しい結果と同じキーを持つ場合は、新しいドキュメントと既存のドキュメントの両方に - reduce関数を適用し、既存のドキュメントを結果で上書きします。
 
- db:- 任意。 map-reduce 操作で出力を書込むデータベースの名前。 デフォルトでは、これは入力コレクションと同じデータベースになります。 
インラインでの出力
メモリ内で map-reduce 操作を実行し、結果を返します。 このオプションは、レプリカセットのセカンダリ ノードでoutのみ使用できるオプションです。
out: { inline: 1 } 
finalize関数の要件
finalize関数のプロトタイプは次のとおりです。
function(key, reducedValue) {    ...    return modifiedObject; } 
finalize関数は、引数としてkey値とreduce関数からのreducedValueを受け取ります。 注意すること:
- finalize関数は、何らかの理由で データベースにアクセスしてはなりません。
- finalize関数は純粋で、関数の外部に影響を与えないようにする必要があります( 副作用はありません。)
- finalize関数は、- scopeパラメータで定義された変数にアクセスできます。
map-reduce の例
このセクションの例には、カスタム集計式を使用しない集計パイプラインの代替手段が含まれています。カスタム式を使用する代替方法については「map-reduce から集計パイプラインへの変換例」を参照してください。
次のドキュメントを含むサンプル コレクションordersを作成します。
db.orders.insertMany([    { _id: 1, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-01"), price: 25, items: [ { sku: "oranges", qty: 5, price: 2.5 }, { sku: "apples", qty: 5, price: 2.5 } ], status: "A" },    { _id: 2, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-08"), price: 70, items: [ { sku: "oranges", qty: 8, price: 2.5 }, { sku: "chocolates", qty: 5, price: 10 } ], status: "A" },    { _id: 3, cust_id: "Busby Bee", ord_date: new Date("2020-03-08"), price: 50, items: [ { sku: "oranges", qty: 10, price: 2.5 }, { sku: "pears", qty: 10, price: 2.5 } ], status: "A" },    { _id: 4, cust_id: "Busby Bee", ord_date: new Date("2020-03-18"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },    { _id: 5, cust_id: "Busby Bee", ord_date: new Date("2020-03-19"), price: 50, items: [ { sku: "chocolates", qty: 5, price: 10 } ], status: "A"},    { _id: 6, cust_id: "Cam Elot", ord_date: new Date("2020-03-19"), price: 35, items: [ { sku: "carrots", qty: 10, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },    { _id: 7, cust_id: "Cam Elot", ord_date: new Date("2020-03-20"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },    { _id: 8, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 75, items: [ { sku: "chocolates", qty: 5, price: 10 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },    { _id: 9, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 55, items: [ { sku: "carrots", qty: 5, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 }, { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },    { _id: 10, cust_id: "Don Quis", ord_date: new Date("2020-03-23"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" } ]) 
カスタマーあたりの合計価格を返す
orders コレクションに対して map-reduce 操作を実行して、cust_idごとにグループ化し、各cust_id の price の合計値を計算します。
- 各入力ドキュメントを処理する map 関数を定義します。 - この関数では、 - thisは map-reduce 操作で処理中のドキュメントを参照します。
- この関数は、各ドキュメントの - priceを- cust_idにマッピングし、- cust_idと- priceを出力します。
 - var mapFunction1 = function() { - emit(this.cust_id, this.price); - }; 
- 2つの引数 - keyCustIdと- valuesPricesを使用して、対応する reduce 関数を定義します。- valuesPricesは、map 関数によって出力され、- keyCustIdでグループ化された- price値を要素とする配列です。
- この関数は - valuesPrice配列をその要素の合計にまで減らします。
 - var reduceFunction1 = function(keyCustId, valuesPrices) { - return Array.sum(valuesPrices); - }; 
- ordersコレクション内のすべてのドキュメントに対して、map 関数- mapFunction1と reduce 関数- reduceFunction1を使用して map-reduce を実行します。- db.orders.mapReduce( - mapFunction1, - reduceFunction1, - { out: "map_reduce_example" } - ) - この操作は、結果を - map_reduce_exampleという名前のコレクションに出力します。- map_reduce_exampleコレクションがすでに存在する場合、この操作により、内容が map-reduce 操作の結果に置き換えられます。
- map_reduce_exampleコレクションをクエリして、結果を検証します。- db.map_reduce_example.find().sort( { _id: 1 } ) - この操作では、次のドキュメントが返されます。 - { "_id" : "Ant O. Knee", "value" : 95 } - { "_id" : "Busby Bee", "value" : 125 } - { "_id" : "Cam Elot", "value" : 60 } - { "_id" : "Don Quis", "value" : 155 } 
集計の代替手段
次のとおり利用可能な集約パイプライン演算子を使用すると、カスタム関数を定義しなくても map-reduce 操作を書き換えることができます。
db.orders.aggregate([    { $group: { _id: "$cust_id", value: { $sum: "$price" } } },    { $out: "agg_alternative_1" } ]) 
- $groupステージは- cust_idでグループ化し、- valueフィールドを計算します(- $sumも参照してください)。- valueフィールドには、各- cust_idの合計- priceが含まれます。- このステージでは、次のドキュメントを次のステージに出力します。 - { "_id" : "Don Quis", "value" : 155 } - { "_id" : "Ant O. Knee", "value" : 95 } - { "_id" : "Cam Elot", "value" : 60 } - { "_id" : "Busby Bee", "value" : 125 } 
- 次に、 - $outにより出力がコレクション- agg_alternative_1に書き込まれます。あるいは、- $outの代わりに- $mergeを使用することもできます
- agg_alternative_1コレクションをクエリして、結果を検証します。- db.agg_alternative_1.find().sort( { _id: 1 } ) - この操作により、次のドキュメントが返されます。 - { "_id" : "Ant O. Knee", "value" : 95 } - { "_id" : "Busby Bee", "value" : 125 } - { "_id" : "Cam Elot", "value" : 60 } - { "_id" : "Don Quis", "value" : 155 } 
Tip
カスタム集計式を使用する代替方法については、「Map-Reduceから集約パイプラインへの変換例」を参照してください。
アイテムごとの平均数量で注文と合計数量を計算
次の例では、orders 上でord_date の値が 2020-03-01 以上となるすべてのドキュメントについての map-reduce 操作を示します。
この例での操作は次のとおりです。
- item.skuフィールドでグループ化し、各- skuの注文数と合計注文数量を計算します。
- 各 - sku値について、1 回の注文あたりの平均数量を計算し、結果を出力コレクションにマージします。
結果をマージするときに、既存のドキュメントが新しい結果と同じキーを持っている場合、操作によって既存のドキュメントが上書きされます。同じキーを持つ既存のドキュメントが存在しない場合は、この操作によってドキュメントが挿入されます。
手順の例:
- 各入力ドキュメントを処理する map 関数を定義します。 - この関数では、 - thisは map-reduce 操作で処理中のドキュメントを参照します。
- 各アイテムについて、この関数では - skuを- countが- 1の新規オブジェクト- value、および注文アイテムの- qtyとと関連付け、- sku(- keyに格納)と- valueを出力します。
 - var mapFunction2 = function() { - for (var idx = 0; idx < this.items.length; idx++) { - var key = this.items[idx].sku; - var value = { count: 1, qty: this.items[idx].qty }; - emit(key, value); - } - }; 
- 2つの引数 - keySKUと- countObjValsを使用して、対応する reduce 関数を定義します。- countObjValsは、map 関数によって reducer 関数に渡される、グループ化された- keySKU値にマップされたオブジェクトを要素とする配列です。
- この関数は - countObjVals配列を- countフィールドと- qtyフィールドを含む 1 つのオブジェクト- reducedValueに縮小します。
- reducedValでは、- countフィールドには個々の配列エレメントの- countフィールドの合計が含まれ、- qtyフィールドには個々の配列エレメントの- qtyフィールドの合計が含まれます。
 - var reduceFunction2 = function(keySKU, countObjVals) { - reducedVal = { count: 0, qty: 0 }; - for (var idx = 0; idx < countObjVals.length; idx++) { - reducedVal.count += countObjVals[idx].count; - reducedVal.qty += countObjVals[idx].qty; - } - return reducedVal; - }; 
- 2 つの引数 - keyと- reducedValを持つ finalize 関数を定義します。この関数は、- reducedValオブジェクトを変更して- avgという名前の計算フィールドを追加し、変更されたオブジェクトを返します。- var finalizeFunction2 = function (key, reducedVal) { - reducedVal.avg = reducedVal.qty/reducedVal.count; - return reducedVal; - }; 
- ordersコレクションに対して map-reduce 操作を実行するには、- mapFunction2、- reduceFunction2、および- finalizeFunction2関数を使用します。- db.orders.mapReduce( - mapFunction2, - reduceFunction2, - { - out: { merge: "map_reduce_example2" }, - query: { ord_date: { $gte: new Date("2020-03-01") } }, - finalize: finalizeFunction2 - } - ); - この操作では、 - queryフィールドを使用して、- ord_dateの値が- new Date("2020-03-01")以上のドキュメントのみを選択します。次に、結果をコレクション- map_reduce_example2に出力します。- map_reduce_example2コレクションがすでに存在する場合、この操作により、内容が map-reduce 操作の結果に置き換えられます。つまり既存のドキュメントが新しい結果と同じキーを持っている場合、操作によって既存のドキュメントが上書きされます。同じキーを持つ既存のドキュメントが存在しない場合は、この操作によってドキュメントが挿入されます。
- map_reduce_example2コレクションをクエリして、結果を検証します。- db.map_reduce_example2.find().sort( { _id: 1 } ) - この操作では、次のドキュメントが返されます。 - { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } } - { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } } - { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } } - { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } } - { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } } 
集計の代替手段
次のとおり利用可能な集約パイプライン演算子を使用すると、カスタム関数を定義しなくても map-reduce 操作を書き換えることができます。
db.orders.aggregate( [    { $match: { ord_date: { $gte: new Date("2020-03-01") } } },    { $unwind: "$items" },    { $group: { _id: "$items.sku", qty: { $sum: "$items.qty" }, orders_ids: { $addToSet: "$_id" } }  },    { $project: { value: { count: { $size: "$orders_ids" }, qty: "$qty", avg: { $divide: [ "$qty", { $size: "$orders_ids" } ] } } } },    { $merge: { into: "agg_alternative_3", on: "_id", whenMatched: "replace",  whenNotMatched: "insert" } } ] ) 
- $matchステージでは、- ord_dateが- new Date("2020-03-01")以上であるドキュメントのみが選択されます。
- $unwindステージでは、- items配列フィールドでドキュメントを分割して、配列要素ごとにドキュメントを出力します。たとえば:- { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 5, "price" : 2.5 }, "status" : "A" } - { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "A" } - { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "oranges", "qty" : 8, "price" : 2.5 }, "status" : "A" } - { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" } - { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" } - { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "A" } - { "_id" : 4, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-18T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" } - { "_id" : 5, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-19T00:00:00Z"), "price" : 50, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" } - ... 
- $groupステージでは各 SKU について計算し、- items.skuでグループ化します。- qtyフィールド。- qtyフィールドには次が含まれます。
- 各items.skuごとに注文されたqtyの合計($sumを参照)。
 
- orders_ids配列。- orders_idsフィールドには次が含まれます。
- items.skuについての、個別の注文の- _id(- $addToSetを参照してください)。
 
 - { "_id" : "chocolates", "qty" : 15, "orders_ids" : [ 2, 5, 8 ] } - { "_id" : "oranges", "qty" : 63, "orders_ids" : [ 4, 7, 3, 2, 9, 1, 10 ] } - { "_id" : "carrots", "qty" : 15, "orders_ids" : [ 6, 9 ] } - { "_id" : "apples", "qty" : 35, "orders_ids" : [ 9, 8, 1, 6 ] } - { "_id" : "pears", "qty" : 10, "orders_ids" : [ 3 ] } 
- $projectステージでは、出力ドキュメントを再形成して、map-reduce の出力をミラーリングし、2 つのフィールド- _idと- valueを含めます。- $projectセット:
- $unwindステージでは、- items配列フィールドでドキュメントを分割して、配列要素ごとにドキュメントを出力します。たとえば:- { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 5, "price" : 2.5 }, "status" : "A" } - { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "A" } - { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "oranges", "qty" : 8, "price" : 2.5 }, "status" : "A" } - { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" } - { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" } - { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "A" } - { "_id" : 4, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-18T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" } - { "_id" : 5, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-19T00:00:00Z"), "price" : 50, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" } - ... 
- $groupステージでは各 SKU について計算し、- items.skuでグループ化します。- qtyフィールド。- qtyフィールドには、- $sumにより、各- items.skuごとに注文された- qtyの合計が含まれます。
- orders_ids配列。- orders_idsフィールドには、- $addToSetにより、- items.skuについての個別の注文- _idの配列が含まれます。
 - { "_id" : "chocolates", "qty" : 15, "orders_ids" : [ 2, 5, 8 ] } - { "_id" : "oranges", "qty" : 63, "orders_ids" : [ 4, 7, 3, 2, 9, 1, 10 ] } - { "_id" : "carrots", "qty" : 15, "orders_ids" : [ 6, 9 ] } - { "_id" : "apples", "qty" : 35, "orders_ids" : [ 9, 8, 1, 6 ] } - { "_id" : "pears", "qty" : 10, "orders_ids" : [ 3 ] } 
- $projectステージでは、出力ドキュメントを再形成して、map-reduce の出力をミラーリングし、2 つのフィールド- _idと- valueを含めます。- $projectセット:- $sizeを使用して、- value.countを- orders_ids配列のサイズに合わせます
- 入力ドキュメントの - qtyフィールドについての- value.qty。
 - { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } } - { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } } - { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } } - { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } } - { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } } 
- 最後に、 - $mergeは出力をコレクション- agg_alternative_3に書き込みます。既存のドキュメントに新しい結果と同じキー- _idがある場合、この操作によって既存のドキュメントが上書きされます。 同じキーを持つ既存のドキュメントが存在しない場合は、この操作によってドキュメントが挿入されます。
- agg_alternative_3コレクションをクエリして、結果を検証します。- db.agg_alternative_3.find().sort( { _id: 1 } ) - この操作により、次のドキュメントが返されます。 - { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } } - { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } } - { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } } - { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } } - { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } } 
Tip
カスタム集計式を使用する代替方法については、「Map-Reduceから集約パイプラインへの変換例」を参照してください。
出力
db.collection.mapReduce()メソッドの出力はmapReduceコマンドの出力と同じです。 出力の詳細については、 mapReducedb.collection.mapReduce()コマンドの 出力 セクションを参照してください。
制限事項
db.collection.mapReduce() afterClusterTime のサポートを終了しました。このため、db.collection.mapReduce() を因果一貫性のあるセッションに関連付けることはできません。