1

我在获得在 CouchDB 1.01 中解决的看似相当简单的问题时遇到了一些问题。我的数据基本上是来自 30 多家诊所的药物日志,其中包含一些关于药物的基本数据和时间戳。我将一组相当普通的对象作为映射结果传递给伪形式的reduce:

Key:ClinicName, Value:{"vaccine":DrugType, "stamp":TimeStamp}

我的 reduce 函数的目的是允许快速参考分配的每种药物的数量。

地图

function(doc) {
   if(doc.type=="dose"){
    emit(doc.clinicName, {"vaccine":doc.vaccine,"stamp":doc.timestamp});
   }
}

减少

function(keys, values){
  var indexes = Object.keys(values);
  var vCount = new Object;
  for (var c in indexes){
    var val = values[c]
    var vname = val.vaccine
    if(vCount.hasOwnProperty(vname)){
      vCount[vname] = vCount[vname] + 1;
    }
    else{
      vCount[vname] = 1;
    }  
  }
  return vCount;
}

当我使用 ?key= 一个特定的 ClinicName 只要descending=false 和group=true 时,这非常有效。一旦设置为真,我的结果就会在中途被切断。

两个问题:

  1. 为什么结果顺序对 reduce 函数很重要?关闭减少后,结果向前和向后是相同的。
  2. 我在某处读到,如果您的归约没有提供单个标量,那么您可能做错了。如果除此之外的奇怪行为是一种糟糕的方法,那么从日志样式数据源中呈现此类数据的正确方法是什么?
4

3 回答 3

1

问题 2 的答案更简单。

“单标量”经验法则非常适合入门,但我看到许多高级应用程序使用对象的方式与您完全一样。

例如,请参阅有关汇总对象中相关值的最新答案:https ://stackoverflow.com/a/10082894/2938

于 2012-04-27T00:51:51.080 回答
1

如果您想知道每个诊所的疫苗数量(计数) ,那么您需要在密钥中使用它。

// pseudo-form
Key:[ClinicName, DrugType], Value:{"stamp":TimeStamp}

接下来,您的 reduce“函数”可以简单地是 string "_count"

有了这个,您可以?group_level=2为每种疫苗在每个诊所设置并获取一行,并分配所有剂量的总和。这可能与您无关,但您可以免费计算每个诊所的剂量(所有药物)?group_level=1

要获得所有诊所的疫苗总数,该观点必须仅针对药物。

// pseudo-form
Key:DrugType, Value:{"stamp":TimeStamp}

主要的一点是,reduce 必须始终在 map 输出中相邻的行上工作。然后您可以使用?group_levelorstartkey/endkey来获得有意义的结果。

于 2012-04-27T01:02:20.380 回答
0

Jason 的回答非常出色且正确,但对于任何偶然发现此问题的人来说,我的根本问题是对 reduce 的工作原理缺乏了解。

最重要的是,reduce 函数的输出本身必须是可归约的,因为 couchdb 并行执行归约。如果你有 1000 行匹配一个键,沙发可能需要 10 组 100 并将函数应用于每个。然后它将重新减少先前减少的 10 个输出,以得出密钥集的解决方案。

最好阅读文档...

阅读 CouchDB 文档的 Reduce/Rereduce 部分

于 2012-08-03T05:41:16.503 回答