如何对具有多个值元素的地图使用couchdb reduce

时间:2014-03-11 02:39:37

标签: mapreduce couchdb

我似乎无法在任何地方找到答案,所以也许这是不允许的,但我无法找到确认这一点的任何couchdb信息。这是一个场景:

假设对于地图功能,在Futon中,我发出一个键的值,例如。 K(1)。该值由密钥K(1)的两个单独的浮点数A(1)和B(1)组成。我希望减少执行比率A(N)/ B(N)在所有K(N)上从1到N的样本平均值。我在reduce函数中总是遇到的问题是"价值观"参数。每个键与(A,B)的值对相关联,但我不能从"值"中分出A,B浮点数。我似乎无法找到有关如何执行此操作的任何示例。我已经尝试过访问"值"的多级javascript数组。但它不起作用,下面是我的地图功能。

function(doc) {
  if(doc['Reqt.ID']) {
    doc['Reqt.ID'].forEach(function(reqt) {
      row_index=doc['Reqt.ID'].indexOf(reqt);
      if(doc.Resource[row_index]=="Joe Smith")
          emit({rid:reqt},{acthrs:doc['Spent.Hours']  [row_index],esthrs:doc['Estimate.Total.Hours'][row_index]});
      });
  }  
}

如果我只生成一个在地图函数中发出单个元素值A / B的地图,我可以让它工作(即平均比率),但我对这个多值元素的情况感到好奇。这通常是如何在Futon减少功能中完成的?

我已经在密钥的for循环中尝试了各种JSON Javascript符号,例如值[key index] .esthrs [0],但我的组合都不起作用。

非常感谢你。

1 个答案:

答案 0 :(得分:2)

有两种方法可以解决这个问题;首先,我的建议是改变你的地图功能,使它更像是“键是键,值是值”,在你的特殊情况下可能意味着,因为你有两个“值”,你想要使用, Spent.HoursEstimate.Total.Hours,您需要两个观点;虽然你可以作弊,但在同一个视图中每行发出多个emit(),例如:

emit(["Spent.Hours", reqt], doc['Spent.Hours'][row_index]);
emit(["Estimate.Total.Hours", reqt], doc['Estimate.Total.Hours'][row_index]);

使用该方法,您可以使用预定义的_stats reduce函数。

或者,您可以定义“智能”统计功能,该功能可以对更精细的文档进行统计。

标准_stats函数提供计数,总和,平均值和标准差。它使用的算法是取值的总和,平方值的总和和值的数量;从这些方面来看,可以计算平均值和标准偏差(并且为了方便起见,将其嵌入到简化视图中)

粗略地说,可能看起来像:

function(key, values, rereduce) {
    function getstats(seq, getter) {
        var c, s, s2 = 0, 0, 0;
        values.forEach(function (row) {
            var value = getter(row);
            if (rereduce) {
                c += value.count;
                s += value.sum;
                s2 += value.sumsq;
            } else {
                c += 1;
                s += value;
                s2 += value * value;
            }
        return {
            count: c,
            sum: s,
            sumsq: s2,
            average: s / c,
            stddev: Math.sqrt(c * s2 - s1) / c
        };
    }
    return {esthrs: getstats(function(x){return x.esthrs}),
            acthrs: getstats(function(x){return x.acthrs})};
}