注意
map-reduce の代替としての集計パイプライン
MongoDB 5.0以降、 map-reduceは非推奨です。
- map-reduceの代わりに、集計パイプラインを使用する必要があります。 集計パイプラインは、map-reduce よりもパフォーマンスとユーザビリティが優れています。 
- $group- $mergeなどの集約パイプライン ステージ を使用して、map-reduce操作を書き換えることができます。
- カスタム機能を必要とする map-reduce 操作には、 - $accumulatorと- $functionの集計演算子を使用できます。 これらの演算子を使用して、JavaScript でカスタム集計式を定義できます。
map-reduce を集計パイプラインに置き換える例については、以下を参照してください。
定義
- mapReduce
- mapReduceコマンドを使用すると、コレクションに対してmap-reduce集計操作を実行できます。- Tip- mongoshでは、このコマンドは- mapReduce()ヘルパー メソッドを通じて実行することもできます。- ヘルパー メソッドは - mongoshユーザーには便利ですが、データベースコマンドと同じレベルの情報は返されない可能性があります。 便宜上必要ない場合、または追加の戻りフィールドが必要な場合は、 データベースコマンドを使用します。
互換性
このコマンドは、次の環境でホストされている配置で使用できます。
- MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです 
重要
このコマンドは、M0 および Flex クラスターではサポートされていません。詳細については、「 サポートされていないコマンド 」を参照してください。
- MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン 
- MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン 
構文
注意
このコマンドの構文は、次のとおりです。
db.runCommand(    {      mapReduce: <string>,      map: <string or JavaScript>,      reduce: <string or JavaScript>,      finalize: <string or JavaScript>,      out: <output>,      query: <document>,      sort: <document>,      limit: <number>,      scope: <document>,      jsMode: <boolean>,      verbose: <boolean>,      bypassDocumentValidation: <boolean>,      collation: <document>,      maxTimeMS: <integer>,      writeConcern: <document>,      comment: <any>    } ) 
コマンドフィールド
コマンドは、次のフィールドを引数として受け取ります。
| フィールド | タイプ | 説明 | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| string | map-reduce を実行するコレクションの名前。 このコレクションは、  ビューでは map-reduce 操作をサポートしていません。 | |||||||||||
| javascript または文字列 | 
 詳細については、「 map 関数の要件 」を参照してください。 | |||||||||||
| javascript または文字列 | 特定の 詳細については、「 reduce 関数の要件 」を参照してください。 | |||||||||||
| 文字列またはドキュメント | map-reduce 操作の結果を出力する場所を指定します。 コレクションに出力することも、結果をインラインで返すこともできます。 レプリカセットのプライマリでは、コレクションまたはインラインでの出力が可能ですが、セカンダリでは、インライン出力のみが可能です。 詳細については、「 アウト オプション 」を参照してください。 | |||||||||||
| ドキュメント | 任意。 | |||||||||||
| ドキュメント | 任意。入力ドキュメントを並べ替えます。このオプションは、最適化に役立ちます。例えば、sort キーを emit キーと同じものに指定すると、reduce 操作の数を減らせます。sort キーは、このコレクションの既存のインデックス内になければなりません。 | |||||||||||
| 数値 | 任意。 | |||||||||||
| javascript または文字列 | 任意。  詳細については、「 finalize 関数の要件 」を参照してください。 | |||||||||||
| ドキュメント | 任意。 | |||||||||||
| ブール値 | 任意。 デフォルトは  
 
 
 
 | |||||||||||
| ブール値 | ||||||||||||
| ブール値 | ||||||||||||
| ドキュメント | 任意。 操作に使用する照合を指定します。 照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。 照合オプションの構文は次のとおりです。 照合を指定する場合、 照合が指定されていなくても、コレクションにデフォルトの照合が設定されている場合( コレクションにも操作にも照合が指定されていない場合、MongoDB では以前のバージョンで使用されていた単純なバイナリ比較によって文字列が比較されます。 1 つの操作に複数の照合は指定できません。たとえば、フィールドごとに異なる照合を指定できません。また、ソートと検索を一度に実行する場合、検索とソートで別の照合を使用できません。 | |||||||||||
| 
 | non-negative integer | 任意。 時間制限をミリ秒単位で指定します。 MongoDB は、 | ||||||||||
| ドキュメント | 任意。 コレクションに出力するときに使用する 書込み保証 ( write concern ) を表すドキュメント。 デフォルトの書込み保証を使用する場合は省略します。 | |||||||||||
| 
 | any | 任意。このコマンドに添付するユーザー指定のコメント。設定すると、このコメントは以下の場所にこのコマンドの記録と合わせて表示されます。 
 コメントには、有効な BSON 型(string, integer, object, array など)を使用できます。 | 
使用法
以下は、 mapReduceコマンドの使用プロトタイプです。
var mapFunction = function() { ... }; var reduceFunction = function(key, values) { ... }; db.runCommand(                {                  mapReduce: <input-collection>,                  map: mapFunction,                  reduce: reduceFunction,                  out: { merge: <output-collection> },                  query: <query>                }              ) 
注意
MongoDB の JavaScript
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 ] ) 
finalize関数の要件
finalize関数のプロトタイプは次のとおりです。
function(key, reducedValue) {    ...    return modifiedObject; } 
finalize関数は、引数としてkey値とreduce関数からのreducedValueを受け取ります。 注意すること:
- finalize関数は、何らかの理由で データベースにアクセスしてはなりません。
- finalize関数は純粋で、関数の外部に影響を与えないようにする必要があります( 副作用はありません。)
- finalize関数は、- scopeパラメータで定義された変数にアクセスできます。
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 } 
必要なアクセス権
MongoDB 配置で認証が強制される場合、 mapReduceコマンドを実行するユーザーは次の特権アクションを持っている必要があります。
{out : inline}出力オプションを使用した map-reduce の例:
コレクションに出力するときに、 replaceアクションを使用して map-reduce を実行します。
コレクションに出力するときに、 mergeまたはreduceアクションを使用して map-reduce を実行します。
readWrite組み込みロール は、map-reduce 集計を実行するために必要な権限を提供します。
制限事項
mapReduceコマンドはafterClusterTimeのサポートを終了しました。 このため、 mapReduceは因果整合性のあるセッション に関連付けることはできません。
map-reduce の例
mongoshでは、 db.collection.mapReduce()メソッドはmapReduceコマンドのラッパーです。 次の例ではdb.collection.mapReduce()メソッドを使用します。
このセクションの例には、カスタム集計式を使用しない集計パイプラインの代替手段が含まれています。カスタム式を使用する代替方法については「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から集約パイプラインへの変換例」を参照してください。
詳細と例については、「 map-reduceページ 」および「 map-reduce の増分実行 」を参照してください
出力
結果をコレクションに書き込むようにアウトパラメーターを設定すると、 mapReduceコマンドは次の形式のドキュメントを返します。
{ "result" : "map_reduce_example", "ok" : 1 } 
アウトパラメータを設定して結果をインラインで出力すると、 mapReduceコマンドは次の形式のドキュメントを返します。
{       "results" : [          {             "_id" : <key>,             "value" :<reduced or finalizedValue for key>          },          ...       ],       "ok" : <int> } 
- mapReduce.result
- コレクションに送信される出力の場合、この値は次のいずれかになります。 - でデータベース名が指定されていない場合のコレクション名の string 、または 
- db- collectionデータベース名とコレクション名の両方が指定さ れ ている場合は、 フィールドと フィールドの両方を含むドキュメント。
 
- mapReduce.results
- インラインで書き込まれた出力の場合、結果ドキュメントの配列。 結果の各ドキュメントには 2 つのフィールドが含まれています。 - _idフィールドには- key値が含まれており、
- valueフィールドには、関連付けられた- keyの減少または確定された値が含まれます。
 
- mapReduce.ok
- 1の値は、- mapReduceコマンドが正常に実行されたことを示します。 値が- 0の場合はエラーを示します。
前述のコマンド固有の戻りフィールドに加えて、 db.runCommand()には追加情報が含まれます。
- レプリカ セットの場合、 - $clusterTimeと- operationTime。
- シャーディングされたクラスターの場合、 - operationTimeおよび- $clusterTime。
これらのフィールドの詳細については db.runCommand レスポンスを参照してください。