Nota
Canalización de agregación como alternativa a Map-Reduce
A partir de MongoDB 5.0, map-reduce está obsoleto:
En lugar de map-reduce, debería usar una canalización de agregación. Las canalizaciones de agregación ofrecen mejor rendimiento y usabilidad que map-reduce.
Puede reescribir las operaciones de map-reduce utilizando etapas de canalización de agregación, como
$group, y$mergeotros.Para las operaciones map-reduce que requieren una funcionalidad personalizada, puedes utilizar los operadores de agregación
$accumulatory$function. Puedes utilizar esos operadores para definir expresiones de agregación personalizadas en JavaScript.
Para ejemplos de alternativas de pipeline de agregación a map-reduce, consulte:
Una canalización de agregación también es más fácil de solucionar que una operación de mapa-reducción.
La reduce función es una función de JavaScript que reduce a un solo objeto todos los valores asociados a una clave específica durante una operación de map-reduce. La reduce función debe cumplir varios requisitos. Este tutorial ayuda a verificar que la reduce función cumple los siguientes criterios:
La
reducefunción debe devolver un objeto cuyo tipo debe ser idéntico al tipo delvalueemitido por lamapfunción.El orden de los elementos en
valuesArrayno debe afectar la salida de la funciónreduce.La
reducefunción debe ser idempotente.
Para obtener una lista de todos los requisitos para la reduce función, consulte mapReduce o mongosh el método db.collection.mapReduce() auxiliar.
Confirmar tipo de salida
Puede probar que la función reduce devuelve un valor que es del mismo tipo que el valor emitido por la función map.
Define una función
reduceFunction1que toma los argumentoskeyCustIdyvaluesPrices.valuesPriceses una matriz de números enteros:var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); }; Define una matriz de muestra de números enteros:
var myTestValues = [ 5, 5, 10 ]; Invocar
reduceFunction1conmyTestValues:reduceFunction1('myKey', myTestValues); Verifique que
reduceFunction1haya devuelto un entero:20 Define una función
reduceFunction2que toma los argumentoskeySKUyvaluesCountObjects.valuesCountObjectses una matriz de documentos que contienen dos camposcountyqty: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; }; Defina una matriz de muestra de documentos:
var myTestObjects = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ]; Invocar
reduceFunction2conmyTestObjects:reduceFunction2('myKey', myTestObjects); Verifique que
reduceFunction2haya devuelto un documento con exactamente los camposcountyqty:{ "count" : 6, "qty" : 30 }
Asegúrese de que no haya sensibilidad al orden de los valores asignados
La función reduce toma como argumento una matriz key y una values. Puede comprobar que el resultado de la función reduce no depende del orden de los elementos en la matriz values.
Define una matriz de muestra
values1y una matriz de muestravalues2que solo difieren en el orden de los elementos de la matriz: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 } ]; Define una función
reduceFunction2que toma los argumentoskeySKUyvaluesCountObjects.valuesCountObjectses una matriz de documentos que contienen dos camposcountyqty: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; }; Invoque primero
reduceFunction2convalues1y luego convalues2:reduceFunction2('myKey', values1); reduceFunction2('myKey', values2); Verifique que
reduceFunction2haya devuelto el mismo resultado:{ "count" : 6, "qty" : 30 }
Asegurar la reducción de la función idempotencia
Como la operación map-reduce puede llamar a reduce varias veces para la misma clave, y no llamará a un reduce para instancias individuales de una clave en el conjunto de trabajo, la función reduce debe devolver un valor del mismo tipo que el valor emitido por la función map. Puedes probar que la función reduce procesa valores "reducidos" sin afectar el valor final.
Define una función
reduceFunction2que toma los argumentoskeySKUyvaluesCountObjects.valuesCountObjectses una matriz de documentos que contienen dos camposcountyqty: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; }; Definir una clave de muestra:
var myKey = 'myKey'; Defina una matriz de muestra
valuesIdempotentque contenga un elemento que sea una llamada a la funciónreduceFunction2:var valuesIdempotent = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, reduceFunction2(myKey, [ { count:3, qty: 15 } ] ) ]; Define una matriz de muestra
values1que combina los valores pasados areduceFunction2:var values1 = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ]; Invoque el
reduceFunction2primero conmyKeyyvaluesIdempotenty luego conmyKeyyvalues1:reduceFunction2(myKey, valuesIdempotent); reduceFunction2(myKey, values1); Verifique que
reduceFunction2haya devuelto el mismo resultado:{ "count" : 6, "qty" : 30 }