调试 Reduce 函数
注意
聚合管道作为 Map-Reduce 的替代方案
从 MongoDB 5.0 开始,map-reduce 已弃用
不再使用 map-reduce,您应使用 聚合管道。聚合管道比 map-reduce 提供更好的性能和可用性。
对于需要自定义功能的map-reduce操作,您可以使用
$accumulator
和$function
聚合运算符。您可以使用这些运算符在JavaScript中定义自定义的聚合表达式。
有关聚合管道替代map-reduce的示例,请参阅
与map-reduce操作相比,聚合管道更容易调试。
reduce函数是一个JavaScript函数,它在map-reduce操作期间将特定键关联的所有值“减少”为单个对象。reduce函数必须满足各种要求。本教程帮助验证reduce函数是否符合以下标准
reduce函数必须返回一个对象,其类型必须与map函数发出的
value
的类型相同。valuesArray中元素的顺序不应影响reduce函数的输出。
reduce函数必须是幂等的。
有关reduce函数的所有要求的列表,请参阅mapReduce
,或mongosh
辅助方法db.collection.mapReduce()
。
确认输出类型
您可以通过测试来验证reduce函数返回的值与来自map函数的值具有相同的类型。
定义一个名为
reduceFunction1
的函数,该函数接收参数keyCustId
和valuesPrices
。其中,valuesPrices
是一个整数数组。var reduceFunction1 = function(keyCustId, valuesPrices) { return Array.sum(valuesPrices); }; 定义一个整数的样本数组。
var myTestValues = [ 5, 5, 10 ]; 使用
myTestValues
调用reduceFunction1
。reduceFunction1('myKey', myTestValues); 验证
reduceFunction1
返回了一个整数。20 定义一个名为
reduceFunction2
的函数,该函数接收参数keySKU
和valuesCountObjects
。其中,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
函数接收一个 key
和一个 values
数组作为参数。您可以测试 reduce
函数的结果是否依赖于 values
数组中元素的顺序。
定义一个样本的
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 } ]; 定义一个名为
reduceFunction2
的函数,该函数接收参数keySKU
和valuesCountObjects
。其中,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
调用reduceFunction2
,然后使用values2
调用。reduceFunction2('myKey', values1); reduceFunction2('myKey', values2); 验证
reduceFunction2
返回了相同的结果。{ "count" : 6, "qty" : 30 }
确保 Reduce 函数幂等性
由于映射-归约操作可能会对同一个键调用多次reduce
,并且对于工作集中单个实例的键不会调用reduce
,因此reduce
函数必须返回与从map
函数发出的值相同类型的值。您可以测试reduce
函数处理“归约”值而不影响最终值。
定义一个名为
reduceFunction2
的函数,该函数接收参数keySKU
和valuesCountObjects
。其中,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 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 } ]; 首先使用
myKey
和valuesIdempotent
调用reduceFunction2
,然后使用myKey
和values1
调用reduceFunction2(myKey, valuesIdempotent); reduceFunction2(myKey, values1); 验证
reduceFunction2
返回了相同的结果。{ "count" : 6, "qty" : 30 }