英文原文地址:https://docs.mongodb.com/v3.2/tutorial/troubleshoot-reduce-function/。
本文章属个人翻译,作个人学习之用,如有雷同,纯属巧合。如有错误之处,欢迎指正。
调试Reduce函数
reduce函数是一个javascript函数,在map-rduce操作过程中把与一个特定键管理的所有值归约为单个对象。reduce函数必须满足多个要求,该教程旨在于验证reduce满足以下要求:
- reduce函数必须返回一个对象,其类型必须与map函数产生的value的类型相同。
- valuesArray中的元素顺序不应该影响reduce函数的输出。
- reduce函数必须是幂等的。
对于reduce函数的所有要求,请查看mapReduce,或者mongo
shell帮助函数db.collection.mapReduce()。
确认输出类型
你可以测试reduce函数返回的值与map函数产生值的类型相同。
定义一个以
keyCustId
和valuesPrice
作为参数的reduceFunction1
函数,valuesPrices
是一个整数数组:var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); };
定义一个整数数组样本:
var myTestValues = [ 5, 5, 10 ];
用
myTestValues
调用myTestValues
:reduceFunction1('myKey', myTestValues);
验证`reduceFunction1,返回一个整数:
20
定义一个以
keySKU
和valuesCountObjects
作为参数的reduceFunction2函数。
valuesCountObjects`是一个文档数组,包含两个字段,count和qty: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; };
定义一个文档数组样本:
var myTestObjects = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ];
用
myTestObjects调用
reduceFunction2`:reduceFunction2('myKey', myTestObjects);
验证
reduceFunction2
,返回的文档仅包含count和qty字段:{ "count" : 6, "qty" : 30 }
确保对映射值的顺序不敏感
reduce函数把一个键和值数组作为它的参数。你可以测试reduce函数的结果不依赖于值数组的元素顺序。
定义一个样例values1数组和样例values2数组,它们只是元素顺序不同:
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 } ];
定义一个以
keySKU
和valuesCountObjects
作为参数的reduceFunction2函数。
valuesCountObjects`是一个文档数组,包含两个字段,count和qty: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; };
依次用values1和values2调用
reduceFunction2
:reduceFunction2('myKey', values1); reduceFunction2('myKey', values2);
验证
reducetFunction2
返回同样的结果:{ "count" : 6, "qty" : 30 }
验证Reduct函数的幂等性
由于map-reduce操作可能对同样的键调用多次reduce,不会只对工作集中的一个键调用一次,reduce函数在不同次数调用与一次调用,返回的值应该是一样的。你可以测试reduce函数处理一个已经归约的值,而不会影响最终的值。
定义一个以
keySKU
和valuesCountObjects
作为参数的reduceFunction2函数。
valuesCountObjects`是一个文档数组,包含两个字段,count和qty: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; };
定义一个样例key:
var myKey = 'myKey';
定义一个样例数组:valuesIdempotent,包含
reduceFunction2
函数的调用结果:var valuesIdempotent = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, reduceFunction2(myKey, [ { count:3, qty: 15 } ] ) ];
定义一个样例数组values1:包含传递给
reduceFunction2
的值:var values1 = [ { count: 1, qty: 5 }, { count: 2, qty: 10 }, { count: 3, qty: 15 } ];
调用
reduceFunction2
,第一次用myKey和valuesIdempotent,第二次用myKey和values1:reduceFunction2(myKey, valuesIdempotent); reduceFunction2(myKey, values1);
验证
reducetFunction2
返回同样的结果:{ "count" : 6, "qty" : 30 }