Solução de problemas da função Reduzir
Nesta página
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
,$merge
e outros.Nas operações de map-reduce que exigem funcionalidade personalizada, você pode usar os operadores de agregação
$accumulator
e$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
reduce
deve retornar um objeto cujo tipo deve ser idêntico ao tipo dovalue
emitido pela funçãomap
.A ordem dos elementos no
valuesArray
não deve afetar a saída da funçãoreduce
.a função
reduce
deve 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
reduceFunction1
que recebe os argumentoskeyCustId
evaluesPrices
.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
reduceFunction1
commyTestValues
:reduceFunction1('myKey', myTestValues); Verifique se o
reduceFunction1
retornou um número inteiro:20 Defina uma função
reduceFunction2
que recebe os argumentoskeySKU
evaluesCountObjects
.valuesCountObjects
é uma matriz de documentos que contêm dois camposcount
eqty
: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
reduceFunction2
commyTestObjects
:reduceFunction2('myKey', myTestObjects); Verifique se o
reduceFunction2
retornou um documento com exatamente ocount
e 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
values1
e uma array de amostravalues2
que 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
reduceFunction2
que recebe os argumentoskeySKU
evaluesCountObjects
.valuesCountObjects
é uma matriz de documentos que contêm dois camposcount
eqty
: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
reduceFunction2
primeiro comvalues1
e depois comvalues2
:reduceFunction2('myKey', values1); reduceFunction2('myKey', values2); Verifique se o
reduceFunction2
retornou 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
reduceFunction2
que recebe os argumentoskeySKU
evaluesCountObjects
.valuesCountObjects
é uma matriz de documentos que contêm dois camposcount
eqty
: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
valuesIdempotent
que 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
values1
que combina os valores passados parareduceFunction2
:var values1 = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ]; Invoque o
reduceFunction2
primeiro commyKey
evaluesIdempotent
e depois commyKey
evalues1
:reduceFunction2(myKey, valuesIdempotent); reduceFunction2(myKey, values1); Verifique se o
reduceFunction2
retornou o mesmo resultado:{ "count" : 6, "qty" : 30 }