Couchdb map/reduce返回流中的第一个,然后按时间排序

Couchdb map/reduce返回流中的第一个,然后按时间排序,couchdb,mapreduce,Couchdb,Mapreduce,我有一个couchdb,里面有一系列的活动。每个事件都有一个所有者、一个id、它发生的时间和一条消息(加上一堆与本练习无关的其他内容)。我想按时间顺序列出最近发生的事件。我仔细阅读了这个问题,并尝试使用它,在缩略器中进行比较,以保留第一条消息(使用我有一个复杂键的表单) 不幸的是,它似乎并没有达到你想要的效果 这是我的地图功能 function(doc) { var owner, id; if (doc.owner && doc.stream_id

我有一个couchdb,里面有一系列的活动。每个事件都有一个所有者、一个id、它发生的时间和一条消息(加上一堆与本练习无关的其他内容)。我想按时间顺序列出最近发生的事件。我仔细阅读了这个问题,并尝试使用它,在缩略器中进行比较,以保留第一条消息(使用我有一个复杂键的表单)

不幸的是,它似乎并没有达到你想要的效果

这是我的地图功能

function(doc) {
  var owner, id;
  if (doc.owner
      && doc.stream_id
      && doc.message
      && doc.receipt_time)
    {
      emit([doc.owner,doc.stream_id,doc.receipt_time],
           { owner: doc.owner,
             stream_id: doc.stream_id,
             timestamp: doc.receipt_time,
             message: doc.message
           });
    }
}
还有我的reduce函数

function(keys, values) {
  var challenger, winner = null;
  for (var a = 0; a < values.length; a++) {
      challenger = values[a];
      if (! winner) {
        winner = challenger;
      } else {
        if (winner.owner !== challenger.owner
            && winner.trace_id !== challenger.trace_id ) {
          return null;
        } else if (challenger.timestamp < winner.timestamp) {
          winner = challenger;
        }
      }
    }
  return winner;
}
(请注意,最终条目实际上是最新的)


所以我希望最终的视图是现在的样子,但按时间排序。有什么方法可以做到这一点吗?

如果我理解正确的话,您不需要筛选事件集合,而只需要对它们进行排序。假设这是正确的,解决方案实际上非常简单,甚至不需要reduce函数。映射函数中发出的键用于对视图进行排序,首先按键中的第一个键排序,然后按键中的其他键排序。换句话说,如果您想按流id排序,然后按接收时间排序,那么对emit的调用如下所示:

emit([doc.stream_id,doc.receipt_time,doc.owner], doc.message);

当然,如果您想按收据时间排序,然后按流id排序,则键应该是
[doc.receipt\u time,doc.stream\u id,doc.owner]
。我认为不需要在键中已经存在的值中包含任何内容,这就是为什么我将该值缩减为仅包含消息的原因。

嗯,我认为最简单的方法实际上是避免该问题

因为我控制发送事件的软件,所以我刚刚在流中的第一个文档中添加了一个
“start”:true,
字段,然后view函数只发送带有该值的事件

这意味着我无法获取历史数据,但这没关系,因为这主要用于检查最近的流

我尝试的另一种选择是添加一个list函数,它在一个键为[timestamp,owner,stream_id]的视图上发送每个所有者stream_id的第一个实例,但是,这会遇到一个问题,即当您限制时,它不会限制最终渲染的列表,而是限制原始视图,因此额外的键目前为止效果最好)


我仍然想知道是否有一些方法可以处理原始数据。

在每条消息的时间戳处存储创建的流。因此,对于第一条消息,您使用当前时间。对于流中的每一条下一条消息,您都会从上一条消息复制它(创建一个视图,以获取流\u created\u at\u by\u stream\u id)

然后创建发出以下信息的视图:

[doc.owner,doc.stream_created_at, doc.stream_id, doc.receipt_time]
这将把来自同一个流的消息分组在一起,同时保持时间顺序。stream.id将确保在同时创建两个流时,来自不同流的消息不会混淆。接收时间将按时间对流中的消息进行排序


所以最终你会得到类似Facebook的对话。您根本不需要任何reduce函数。

我想您是误解了。对于任何一个所有者+流id,最多可以有数千条消息。我想显示每个流中的第一条消息,然后按时间戳排序。如果您订购它们[owner,stream\u id,receive\u time],那么使用group\u level 2和我概述的reduce函数,我会按所有者和stream\u id获得每个流的第一条消息,但它们根据时间的顺序不正常。如果我将接收时间(即第三级组)包括在内,我会收到每一条信息,因此这与目的背道而驰。你是对的,我确实误解了。我认为可能还有一种更简单的方法可以做到,但我必须考虑一下。也许其中一位沙发专家会在这段时间来提供答案。
[doc.owner,doc.stream_created_at, doc.stream_id, doc.receipt_time]