翻译或纠错本页面

验证Reduce函数

reduce是用 JavaScript 编写的函数。它在 map-reduce 操作中可以把一个键的所有值合并到一个单独的对象中。 reduce 函数必须满足一系列的要求。本章节介绍如何验证 reduce 函数是否满足了这些场景:

  • reduce函数返回的对象类型必须和map函数提交的对象类型一样。

  • 数组 valuesArray 中元素的顺序不应该影响 reduce 函数的输出结果。

  • reduce函数必须是 幂等

reduce函数必须要满足几个条件,详细的列表可以查看 mapReduce ,或者 mongo 命令行下的 db.collection.mapReduce()

确认输出的类型

你可以验证一下 reduce 函数返回的对象类型是否和 map 提交的类型是一样的。

  1. 定义 reduceFunction1 函数,它的入参是两个参数 keyCustIdvaluesPrices。其中 valuesPrices 是一个整形变量数组:

    var reduceFunction1 = function(keyCustId, valuesPrices) {
                              return Array.sum(valuesPrices);
                          };
    
  2. 定义一个整型变量的数组:

    var myTestValues = [ 5, 5, 10 ];
    
  3. myTestValues 传入 reduceFunction1

    reduceFunction1('myKey', myTestValues);
    
  4. 检查 reduceFunction1 返回的整型值:

    20
    
  5. 定义一个函数 reduceFunction2 ,它的入参是 keySKUvaluesCountObjectsvaluesCountObjects 是一个数组,数组中的每个文档包含两个字段 countqty

    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;
                          };
    
  6. 定义一个文档数组:

    var myTestObjects = [
                          { count: 1, qty: 5 },
                          { count: 2, qty: 10 },
                          { count: 3, qty: 15 }
                        ];
    
  7. myTestObjects 数组传入 reduceFunction2

    reduceFunction2('myKey', myTestObjects);
    
  8. 检查 reduceFunction2 函数返回的文档中的 countqty 的值:

    { "count" : 6, "qty" : 30 }
    

对映射的值排序时不区分大小写

reduce的入参是一个 key 和数组 values ,你可以测试验证 reduce 的输出结果与 values 数组中元素的顺序是无关的。

  1. 定义两个数组 values1values2 ,它们包含的元素顺序是不一样的:

    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 }
                  ];
    
  2. 定义一个函数 reduceFunction2 ,它的入参是 keySKUvaluesCountObjectsvaluesCountObjects 是一个数组,数组中的每个文档包含两个字段 countqty

    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;
                          };
    
  3. 依次对 values1values2 调用 reduceFunction2

    reduceFunction2('myKey', values1);
    reduceFunction2('myKey', values2);
    
  4. 检查 reduceFunction2 函数两次的返回值是否都是下面的值:

    { "count" : 6, "qty" : 30 }
    

确保Reduce函数是幂等的

由于在整个map-reduce过程中,对于同一个键值可能会调用多次 reduce ,但是输出到结果集的记录不会调用 reduce 。并且 reduce 返回的值类型和 map 提交的值类型一样。你可以测试一下 reduce 函数在调用多次的时候,不会影响最终的值:

  1. 定义一个函数 reduceFunction2 ,它的入参是 keySKUvaluesCountObjectsvaluesCountObjects 是一个数组,数组中的每个文档包含两个字段 countqty

    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;
                          };
    
  2. 定义一个键:

    var myKey = 'myKey';
    
  3. 定义接下来 reduceFunction2 函数要处理的一个数组 valuesIdempotent

    var valuesIdempotent = [
                             { count: 1, qty: 5 },
                             { count: 2, qty: 10 },
                             reduceFunction2(myKey, [ { count:3, qty: 15 } ] )
                           ];
    
  4. 定义包含了这些值的一个数组 values1

    var values1 = [
                    { count: 1, qty: 5 },
                    { count: 2, qty: 10 },
                    { count: 3, qty: 15 }
                  ];
    
  5. 首先使用 reduceFunction2 处理 myKeyvaluesIdempotent ,然后再处理 myKeyvalues1

    reduceFunction2(myKey, valuesIdempotent);
    reduceFunction2(myKey, values1);
    
  6. 检查 reduceFunction2 函数两次的返回值是否都是下面的值:

    { "count" : 6, "qty" : 30 }