Nosql CouchDB的特殊映射/还原结果

Nosql CouchDB的特殊映射/还原结果,nosql,couchdb,mapreduce,Nosql,Couchdb,Mapreduce,我已经使用CouchDB很长一段时间了,没有任何问题。到现在为止。我最近在我的map/reduce结果中看到了一些我忽略了的东西 这是在对“avgs”变量执行求和之前。我基本上是想找到与某个键相关的所有值的平均值。没什么特别的。结果如预期 注意时间戳1308474660000的结果(表中第4行): 现在我sumavgs数组。现在,这个结果有点特别。时间戳为1308474660000的密钥的总和为null!!为什么CouchDB在简单的求和时会吐出nulls?我尝试了一个自定义的加法函数,它也

我已经使用CouchDB很长一段时间了,没有任何问题。到现在为止。我最近在我的map/reduce结果中看到了一些我忽略了的东西

这是在对“avgs”变量执行求和之前。我基本上是想找到与某个键相关的所有值的平均值。没什么特别的。结果如预期

注意时间戳1308474660000的结果(表中第4行):


现在我
sum
avgs数组。现在,这个结果有点特别。时间戳为1308474660000的密钥的总和为
null
!!为什么CouchDB在简单的求和时会吐出
null
s?我尝试了一个自定义的加法函数,它也有同样的问题

function(keys, values, rereduce) {
  if(rereduce)
     return sum(values);

  // ... then the same code as before.
}
有人能给我解释一下为什么我的map/reduce结果会出现这个问题吗

CouchDB版本:1.0.1


更新:

在执行rereduce之后,我得到一个REDUCT溢出错误

Error: reduce_overflow_error

Reduce output must shrink more rapidly: Current output: '["001,1,1,1,1,1,11,1,1,1,1,1,1,11,1,1,1,1,1,1,11,1,1,1,1,1,1,11,1,1,1,1,1,101,1,1,1,1,1,1,11,1,1,1,1'... (first 100 of 396 bytes)
这是我修改过的reduce函数:

function (key, values, rereduce) {
  if(!rereduce) {
    var avgs = [];
    for(var i=values.length-1; i>=0 ; i--) {
      avgs.push(Number(values[i][0])/Number(values[i][1]));
    }
    return avgs;
  } else {
    return sum(values);
  };
}

更新2:

现在情况变得更糟了。它有选择地重新推导。此外,它重新得出的结果显示错误。时间戳(1308474660000)第4行中的值的长度应为2,而不是3

更新3:

我终于成功了。我没有正确理解重新教育的具体内容。好吧,Couchdb自己决定如何/何时重新导出。在本例中,只要数组足够长,可以进行处理,Couchdb就会将其发送给rereduce。所以我基本上要求两次。一次减少,一次减少

function (key, values, rereduce) {
  if(!rereduce) {
    var avgs = [];
    for(var i=values.length-1; i>=0 ; i--) {
      avgs.push(Number(values[i][0])/Number(values[i][1]));
    }
    return sum(avgs);
  } else {
    return sum(values); //If my understanding of rereduce is correct, it only receives only the avgs that are large enough to not be processed by reduce.
  }
}

reduce函数中的
for
循环可能没有按您认为的那样执行。例如,它可能会抛出一个您没有预料到的异常

您需要一个2元组数组:

// Expectation
values = [ [value1, total1]
         , [value2, total2]
         , [value3, total3]
         ];
在重新reduce过程中,函数将从以前的函数中获得旧的结果

// Re-reduce values
values = [ avg1
         , avg2
         , avg3
         ]
因此,如果
rereduce
为真,我将首先检查您的代码是如何工作的。也许一些简单的方法可以解决它(尽管在我找到问题之前,我通常必须
log()
记录一些事情)


我将详细说明我的计数/总和评论,以防您好奇

这段代码没有经过测试,但希望您能理解。最终的结果总是一个简单的对象
{“count”:C,“sum”:S}
,通过计算
S/C
知道平均值

function (key, values, rereduce) {
  // Reduce function
  var count = 0;
  var sum = 0;
  var i;

  if(!rereduce) {
    // `values` stores actual map output
    for(i = 0; i < values.length; i++) {
      count += Number(values[i][1]);
      sum += Number(values[i][0]);
    }

    return {"count":count, "sum":sum};
  }

  else {
    // `values` stores count/sum objects returned previously.
    for(i = 0; i < values.length; i++) {
      count += values[i].count;
      sum   += values[i].sum;
    }

    return {"count":count, "sum":sum};
  }
}
函数(键、值、返回值){
//还原函数
var计数=0;
var总和=0;
var i;
如果(!REREREDUCE){
//`values`存储实际地图输出
对于(i=0;i
我使用以下代码进行平均。希望能有帮助

function (key, values) {
    return sum(values)/values.length;    
}

跟进:我用CouchBase/BigCoach尝试了同样的方法,它正确地计算了时间戳的
sum
,但对其他键显示了
null
s。奇怪@谢谢你的解决方案。等了很久才有人回复。我会试试,然后回复。但是,您能解释一下您是如何在coach中
log()
的吗?我想没有办法
log
/
console.log
。这对我来说会更容易。非常感谢!:)我想你的问题已经解决了。下一个错误与此无关。(Reduce必须减少数据量,而不是简单地将其转换为不同的格式,即数组。)此外,这是否可能是数据中混合的字符串?看起来可能是字符串
“001”
触发了串联而不是数字相加。没有字符串。我确信这一点。另外,我还把结果作为额外的预防措施。见图1<代码>编号(值[i][0])。到目前为止,我还没有再做一次。我只是将数组发送给客户端,客户端计算平均值。因此,如果它在客户端工作,那么它也应该在CouchDB中工作,对吗?好的。问题的更新并没有显示我在计算值和总数。然而,我是在reduce视图中进行的。事实上,如果我只是返回
而不是返回
,那么数组本身就会得到一个
null
。所以Couchdb出于某种奇怪的原因正在传递
null
而不是数组来重新导出。啊!这很好。大多数情况下都有效。然而,在我的例子中,我存储预计算的值和计数,只需要找到平均值。所以我也这么做了,只是为了平均水平。详细说明:对于特定的时间戳,我有一个通过redis计算的键的值/计数(在某些情况下,mongodb..取决于数据的类型)。然后我将其存储到couchdb中用于报告/绘制图表。:)使用map/reduce仅计算平均值(值/计数)。我想你有一个讨厌的现实要求:)