CouchDB函数以给定间隔对记录进行采样。

时间:2011-05-19 15:21:45

标签: couchdb reduce

我有时间值的记录,需要能够在一段时间内查询它们,并且只返回给定间隔的记录。

例如,我可能需要从12点到1点的所有记录,每隔10分钟给我12:00,12:10,12:20,12:30,... 12:50,01: 00。间隔需要是一个参数,它可以是任何时间值。 15分47秒1.4小时。

我尝试做某种减少,但这显然是错误的做法。

这是我想出的。欢迎评论。

为时间字段创建了一个视图,以便查询一系列时间。视图输出id和时间。

function(doc) { 
  emit([doc.rec_id, doc.time], [doc._id, doc.time]) 
}

然后我创建了一个列表函数,它接受一个名为interval的参数。在list函数中,我通过行工作并将当前行的时间与最后接受的时间进行比较。如果跨度大于或等于间隔,我将行添加到输出中,并将JSON-ify添加到输出中。

function(head, req) { 

  // default to 30000ms or 30 seconds.
  var interval = 30000; 

  // get the interval from the request.
  if (req.query.interval) {
    interval = req.query.interval; 
  }

  // setup
  var row; 
  var rows = []; 
  var lastTime = 0; 

  // go thru the results...
  while (row = getRow()) { 
      // if the time from view is more than the interval 
      // from our last time then add it.
      if (row.value[1] - lastTime > interval) { 
          lastTime = row.value[1]; 
          rows.push(row); 
      } 
  } 
  // JSON-ify!
  send(JSON.stringify({'rows' : rows}));
}

到目前为止,这种方法运作良好。我将针对一些大数据进行测试,以了解性能如何。关于如何更好地完成这项工作的任何意见,或者这是否是沙发的正确方法?

1 个答案:

答案 0 :(得分:1)

CouchDB很放松。如果这对您有用,那么我会坚持下去并专注于您的下一个优先事项。

一个快速优化是尽量不在_list函数中建立最终答案,而是在你知道的答案的send()小部分。这样,您的函数可以在无限的结果大小上运行。

但是,正如您所怀疑的那样,您基本上使用_list函数进行即席查询,这可能会因您的数据库大小增加而出现问题。

我不是100%确定你需要什么,但如果你在一个时间范围内寻找文件,那么emit()密钥很可能主要按时间排序。 (在您的示例中,主要(最左侧)排序值为doc.rec_id。)

对于地图功能:

function(doc) {
  var key = doc.time; // Just sort everything by timestamp.
  emit(key, [doc._id, doc.time]);
}

这将构建按time时间戳排序的所有文档的地图。 (我假设时间值类似于JSON.stringify(new Date),即"2011-05-20T00:34:20.847Z"

要查找1小时内的所有文档,只需使用?startkey="2011-05-20T00:00:00.000Z"&endkey="2011-05-20T01:00:00.000Z"查询地图视图。

如果我正确理解你的“间隔”标准,那么如果你需要10分钟的间隔,那么如果你有00:00,00:15,00:00,00:45,00:50,那么只有00: 00,00:00,00:50应该在最终结果中。因此,您过滤正常沙发输出以消除不需要的结果。对_list函数来说,这是一个完美的工作。只需使用req.query.interval并且仅send()匹配间隔的行。