Nota
Pipeline de agregación como alternativa a Map-Reduce
A partir de MongoDB 5.0, El map-reduce está en desuso:
En lugar de map-reduce, debes usar un pipeline de agregación. Los pipelines de agregación ofrecen un mejor rendimiento y usabilidad que map-reduce.
Puedes reescribir las operaciones de map-reduce usando etapas del pipeline de agregación, como
$group,$mergey otros.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 pipeline de agregación también es más fácil de solucionar que una operación map-reduce.
La función reduce es una función de JavaScript que "reduce" en un solo objeto todos los valores asociados a una clave en particular durante una operación map-reduce. La función reduce debe cumplir varios requisitos. Este tutorial ayuda a verificar que la función reduce cumpla con los siguientes criterios:
La
reducefunción debe retornar un objeto cuyo tipo debe ser idéntico al tipo delvalueemitido por la funciónmap.El orden de los elementos en la
valuesArrayno debe afectar la salida de la funciónreduce.La función
reducedebe ser idempotente.
Para obtener una lista de todos los requisitos para la función reduce, consulta mapReduce o mongosh método asistente db.collection.mapReduce().
Confirme el 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 tome los argumentoskeyCustIdyvaluesPrices.valuesPriceses un arreglo de enteros:var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); }; Definir un arreglo de enteros de muestra:
var myTestValues = [ 5, 5, 10 ]; Invoca el
reduceFunction1conmyTestValues:reduceFunction1('myKey', myTestValues); Verifique que el
reduceFunction1devolvió un número entero:20 Define una función
reduceFunction2que tome los argumentoskeySKUyvaluesCountObjects.valuesCountObjectses un arreglo de documentos que contiene dos campos,countyqty: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 un arreglo de muestra de documentos:
var myTestObjects = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ]; Invoca el
reduceFunction2conmyTestObjects:reduceFunction2('myKey', myTestObjects); Verifica que el
reduceFunction2devolvió un documento con exactamente elcounty el campoqty:{ "count" : 6, "qty" : 30 }
Asegurar la insensibilidad al orden de los valores mapeados
La función reduce toma un key y un arreglo values como argumento. Puedes verificar que el resultado de la función reduce no depende del orden de los elementos en el arreglo values.
Define un arreglo de muestra
values1y un arreglo de muestravalues2que solo difieran en el orden de los elementos del arreglo: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 tome los argumentoskeySKUyvaluesCountObjects.valuesCountObjectses un arreglo de documentos que contiene dos campos,countyqty: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; }; Invoca el
reduceFunction2primero convalues1y luego convalues2:reduceFunction2('myKey', values1); reduceFunction2('myKey', values2); Verifique que el
reduceFunction2devolvió el mismo resultado:{ "count" : 6, "qty" : 30 }
Asegurar la idempotencia de la función reducir
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 tome los argumentoskeySKUyvaluesCountObjects.valuesCountObjectses un arreglo de documentos que contiene dos campos,countyqty: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'; Define un arreglo de ejemplo de
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 muestra
values1de arreglo que combine los valores que se pasan 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 el
reduceFunction2devolvió el mismo resultado:{ "count" : 6, "qty" : 30 }