注意
map-reduce の代替としての集計パイプライン
MongoDB 5.0以降、 map-reduceは非推奨です。
map-reduceの代わりに、集計パイプラインを使用する必要があります。 集計パイプラインは、map-reduce よりもパフォーマンスとユーザビリティが優れています。
$group$mergeなどの集約パイプライン ステージ を使用して、map-reduce操作を書き換えることができます。カスタム機能を必要とする map-reduce 操作には、
$accumulatorと$functionの集計演算子を使用できます。 これらの演算子を使用して、JavaScript でカスタム集計式を定義できます。
map-reduce を集計パイプラインに置き換える例については、以下を参照してください。
また、map-reduce 操作よりも集計パイプラインの方がトラブルシューティングが簡単です。
reduce関数は、 map-reduce操作中に特定のキーに関連付けられたすべての値を 1 つのオブジェクトに削減する JavaScript 関数です。 reduce関数はさまざまな要件を満たしている必要があります。 このチュートリアルは、 reduce関数が次の条件を満たしていることを確認するのに役立ちます。
reduce関数は、map関数によって出力されるvalueの型と同一である必要があるオブジェクトを返す必要があります。valuesArray内の要素の順序は、reduce関数の出力には影響しません。reduce関数は冪等である必要があります。
reduce関数のすべての要件のリストについては、 mapReduceまたはmongoshヘルパー メソッドdb.collection.mapReduce()を参照してください。
出力タイプの確認
reduce関数がmap関数から出力する値と同じ型の値を返すことをテストできます。
keyCustIdとvaluesPrices引数を持つreduceFunction1関数を定義します。valuesPricesは整数の配列です。var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); }; 整数のサンプル配列を定義します。
var myTestValues = [ 5, 5, 10 ]; を使用して
reduceFunction1myTestValuesを呼び出します。reduceFunction1('myKey', myTestValues); reduceFunction1が整数を返したことを確認します。20 keySKUとvaluesCountObjects引数を持つreduceFunction2関数を定義します。valuesCountObjectsは、2 つのフィールドcountとqtyを含むドキュメントの配列です。var reduceFunction2 = function(keySKU, valuesCountObjects) { reducedValue = { count: 0, qty: 0 }; for (var idx = 0; idx < valuesCountObjects.length; idx++) { reducedValue.count += valuesCountObjects[idx].count; reducedValue.qty += valuesCountObjects[idx].qty; } return reducedValue; }; ドキュメントのサンプル配列を定義します。
var myTestObjects = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ]; を使用して
reduceFunction2myTestObjectsを呼び出します。reduceFunction2('myKey', myTestObjects); reduceFunction2がcountフィールドと フィールドのみを含むドキュメントを返したことを確認します。qty{ "count" : 6, "qty" : 30 }
マップされた値の順序を区別しないようにする
reduce関数は、引数としてkeyとvalues配列を受け取ります。 reduce関数の結果がvalues配列内の要素の順序に依存しないことをテストできます。
配列要素の順序のみが異なるサンプル
values1配列とサンプルvalues2配列を定義します。var values1 = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ]; var values2 = [ { count: 3, qty: 15 }, { count: 1, qty: 5 }, { count: 2, qty: 10 } ]; keySKUとvaluesCountObjects引数を持つreduceFunction2関数を定義します。valuesCountObjectsは、2 つのフィールドcountとqtyを含むドキュメントの配列です。var reduceFunction2 = function(keySKU, valuesCountObjects) { reducedValue = { count: 0, qty: 0 }; for (var idx = 0; idx < valuesCountObjects.length; idx++) { reducedValue.count += valuesCountObjects[idx].count; reducedValue.qty += valuesCountObjects[idx].qty; } return reducedValue; }; 最初に
values1を使用してreduceFunction2を呼び出し、次にvalues2を使用して を呼び出します。reduceFunction2('myKey', values1); reduceFunction2('myKey', values2); reduceFunction2が同じ結果を返したことを確認します。{ "count" : 6, "qty" : 30 }
関数の冪等性を確実に減らす
map-reduce 操作では、同じキーに対してreduceが複数回呼び出される可能性があり、ワーキングセット内のキーの単一のインスタンスに対してreduceが呼び出されないため、 reduce関数は次の値を返す必要があります: map関数から出力される値と同じ型。 reduce関数が最終値に影響を与えずに「削減された」値を処理することをテストできます。
keySKUとvaluesCountObjects引数を持つreduceFunction2関数を定義します。valuesCountObjectsは、2 つのフィールドcountとqtyを含むドキュメントの配列です。var reduceFunction2 = function(keySKU, valuesCountObjects) { reducedValue = { count: 0, qty: 0 }; for (var idx = 0; idx < valuesCountObjects.length; idx++) { reducedValue.count += valuesCountObjects[idx].count; reducedValue.qty += valuesCountObjects[idx].qty; } return reducedValue; }; サンプルキーを定義します。
var myKey = 'myKey'; reduceFunction2関数の呼び出しである要素を含むサンプルvaluesIdempotent配列を定義します。var valuesIdempotent = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, reduceFunction2(myKey, [ { count:3, qty: 15 } ] ) ]; reduceFunction2に渡される値を組み合わせたサンプルvalues1配列を定義します。var values1 = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ]; 最初に
myKeyとvaluesIdempotentを使用してreduceFunction2を呼び出し、次にmyKeyとvalues1を使用して を呼び出します。reduceFunction2(myKey, valuesIdempotent); reduceFunction2(myKey, values1); reduceFunction2が同じ結果を返したことを確認します。{ "count" : 6, "qty" : 30 }