Observação
Pipeline de Agregação como Alternativa à Redução de Mapa
A partir do MongoDB , 5.0, map-reduce está obsoleto:
Em vez de map-reduce, você deve usar um aggregation pipeline. aggregation pipeline fornece melhor desempenho e usabilidade do que a redução de mapa.
Você pode reescrever operações de redução de mapa utilizando estágios do pipeline de agregação, como
$group,$mergee outros.Nas operações de map-reduce que exigem funcionalidade personalizada, você pode usar os operadores de agregação
$accumulatore$function. Você pode usar esses operadores para definir expressões de agregação personalizadas no JavaScript.
Para obter exemplos de alternativas de aggregation pipeline para map-reduce, consulte:
Um aggregation pipeline também é mais fácil de solucionar problemas do que uma operação de map-reduce.
A função reduce é uma função JavaScript que "reduz" a um único objeto todos os valores associados a uma chave específica durante uma operação de map-reduce . A função reduce deve atender a vários requisitos. Este tutorial ajuda a verificar se a função reduce atende aos seguintes critérios:
A função
reducedeve retornar um objeto cujo tipo deve ser idêntico ao tipo dovalueemitido pela funçãomap.A ordem dos elementos no
valuesArraynão deve afetar a saída da funçãoreduce.a função
reducedeve ser idempotente.
Para obter uma lista de todos os requisitos da função reduce , consulte mapReduce ou mongosh método auxiliar db.collection.mapReduce().
Confirmar tipo de saída
Você pode testar que a função reduce retorna um valor que é do mesmo tipo que o valor emitido da função map .
Defina uma função
reduceFunction1que recebe os argumentoskeyCustIdevaluesPrices.valuesPricesé uma matriz de números inteiros:var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); }; Defina uma array de amostra de números inteiros:
var myTestValues = [ 5, 5, 10 ]; Invoque o
reduceFunction1commyTestValues:reduceFunction1('myKey', myTestValues); Verifique se o
reduceFunction1retornou um número inteiro:20 Defina uma função
reduceFunction2que recebe os argumentoskeySKUevaluesCountObjects.valuesCountObjectsé uma matriz de documentos que contêm dois camposcounteqty: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 uma amostra de array de documentos:
var myTestObjects = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ]; Invoque o
reduceFunction2commyTestObjects:reduceFunction2('myKey', myTestObjects); Verifique se o
reduceFunction2retornou um documento com exatamente ocounte o campoqty:{ "count" : 6, "qty" : 30 }
Garanta a insensibilidade à ordem dos valores mapeados
A função reduce usa uma array key e uma array values como argumento. Você pode testar que o resultado da função reduce não depende da ordem dos elementos na array values .
Defina uma array de amostra
values1e uma array de amostravalues2que diferem apenas na ordem dos elementos da array: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 } ]; Defina uma função
reduceFunction2que recebe os argumentoskeySKUevaluesCountObjects.valuesCountObjectsé uma matriz de documentos que contêm dois camposcounteqty: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 o
reduceFunction2primeiro comvalues1e depois comvalues2:reduceFunction2('myKey', values1); reduceFunction2('myKey', values2); Verifique se o
reduceFunction2retornou o mesmo resultado:{ "count" : 6, "qty" : 30 }
Certifique-se de reduzir a idempotência da função
Como a operação de map-reduce pode chamar um reduce várias vezes para a mesma chave e não chamará um reduce para instâncias únicas de uma chave no conjunto de trabalho, a função reduce deve retornar um valor do mesmo tipo que o valor emitido da função map . Você pode testar se a função reduce processa valores "reduzidos" sem afetar o valor final .
Defina uma função
reduceFunction2que recebe os argumentoskeySKUevaluesCountObjects.valuesCountObjectsé uma matriz de documentos que contêm dois camposcounteqty: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 uma chave de amostra:
var myKey = 'myKey'; Defina um array de amostra
valuesIdempotentque contém um elemento que é uma chamada para a funçãoreduceFunction2:var valuesIdempotent = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, reduceFunction2(myKey, [ { count:3, qty: 15 } ] ) ]; Defina um array de amostra
values1que combina os valores passados parareduceFunction2:var values1 = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ]; Invoque o
reduceFunction2primeiro commyKeyevaluesIdempotente depois commyKeyevalues1:reduceFunction2(myKey, valuesIdempotent); reduceFunction2(myKey, values1); Verifique se o
reduceFunction2retornou o mesmo resultado:{ "count" : 6, "qty" : 30 }