- Aggregation >
- Map-Reduce >
- Troubleshoot the Reduce Function
Troubleshoot the Reduce Function¶
On this page
The reduce
function is a JavaScript function that “reduces” to a
single object all the values associated with a particular key during a
map-reduce operation. The reduce
function
must meet various requirements. This tutorial helps verify that the
reduce
function meets the following criteria:
- The
reduce
function must return an object whose type must be identical to the type of thevalue
emitted by themap
function. - The order of the elements in the
valuesArray
should not affect the output of thereduce
function. - The
reduce
function must be idempotent.
For a list of all the requirements for the reduce
function, see
mapReduce
, or the mongo
shell helper method
db.collection.mapReduce()
.
Confirm Output Type¶
You can test that the reduce
function returns a value that is the
same type as the value emitted from the map
function.
Define a
reduceFunction1
function that takes the argumentskeyCustId
andvaluesPrices
.valuesPrices
is an array of integers:var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); };
Define a sample array of integers:
var myTestValues = [ 5, 5, 10 ];
Invoke the
reduceFunction1
withmyTestValues
:reduceFunction1('myKey', myTestValues);
Verify the
reduceFunction1
returned an integer:20
Define a
reduceFunction2
function that takes the argumentskeySKU
andvaluesCountObjects
.valuesCountObjects
is an array of documents that contain two fieldscount
andqty
: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; };
Define a sample array of documents:
var myTestObjects = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ];
Invoke the
reduceFunction2
withmyTestObjects
:reduceFunction2('myKey', myTestObjects);
Verify the
reduceFunction2
returned a document with exactly thecount
and theqty
field:{ "count" : 6, "qty" : 30 }
Ensure Insensitivity to the Order of Mapped Values¶
The reduce
function takes a key
and a values
array as its
argument. You can test that the result of the reduce
function does
not depend on the order of the elements in the values
array.
Define a sample
values1
array and a samplevalues2
array that only differ in the order of the array elements: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 a
reduceFunction2
function that takes the argumentskeySKU
andvaluesCountObjects
.valuesCountObjects
is an array of documents that contain two fieldscount
andqty
: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; };
Invoke the
reduceFunction2
first withvalues1
and then withvalues2
:reduceFunction2('myKey', values1); reduceFunction2('myKey', values2);
Verify the
reduceFunction2
returned the same result:{ "count" : 6, "qty" : 30 }
Ensure Reduce Function Idempotence¶
Because the map-reduce operation may call a reduce
multiple times
for the same key, and won’t call a reduce
for single instances
of a key in the working set, the reduce
function must return a value of the
same type as the value emitted from the map
function. You can test
that the reduce
function process “reduced” values without
affecting the final value.
Define a
reduceFunction2
function that takes the argumentskeySKU
andvaluesCountObjects
.valuesCountObjects
is an array of documents that contain two fieldscount
andqty
: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; };
Define a sample key:
var myKey = 'myKey';
Define a sample
valuesIdempotent
array that contains an element that is a call to thereduceFunction2
function:var valuesIdempotent = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, reduceFunction2(myKey, [ { count:3, qty: 15 } ] ) ];
Define a sample
values1
array that combines the values passed toreduceFunction2
:var values1 = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ];
Invoke the
reduceFunction2
first withmyKey
andvaluesIdempotent
and then withmyKey
andvalues1
:reduceFunction2(myKey, valuesIdempotent); reduceFunction2(myKey, values1);
Verify the
reduceFunction2
returned the same result:{ "count" : 6, "qty" : 30 }