重新排序缩小视图的结果

问题描述 投票:1回答:1

请考虑以下文档结构:

线程:

 - doc_type   1
 - _id        
 - subject    (string)

职位:

 - doc_type   2
 - _id        
 - thread_id  (_id of Thread)
 - time       (milliseconds since 1970)
 - comment    (string)

我需要按主题的最后一个帖子以及最新的5个帖子排序的主题。我认为避免每次执行新文章后都更新线程文档,以消除跨db节点的分布式环境中发生冲突的可能性。此外,它将为数据库工作,而数据库应该为您工作。

为了简单起见,让我们从查找最新帖子开始。 5条帖子可以用相同的方式收集。

现在,我不确定我的方向正确,但是,看着here,我发现如何使用reduce函数在线程中找到最后一个帖子,reduce函数使用组级别返回从doc类型1,以及最后一个发布文档取自doc类型2。

顺便说一句-与链接中的示例相反,在我的情况下,始终创建具有第一篇文章的线程(例如,线程的创建日期将是其第一篇文章的日期)。

map:

function(doc){
  switch(doc.doc_type){
     case 1: emit([doc._id],doc); return;
     case 2: emit([doc.thread_id],doc); return;
  }
}

reduce:在现实世界中,密钥比较复杂,因此必须与适当的组级别一起使用。为了简单起见,在这里我也忽略了重新减少的情况。您可以找到完整图片here

function(keys, vals, rr){
   var result = { subject: null, lastPost: null, count :0 };
   //I'll ignore the re-reduce case for simplicity
   vals.forEach(function(doc){
      switch(doc.doc_type){
         case 1: 
            result.subject = doc.subject; 
            return;
         case 2: 
            if (result.lastPost.time < doc.time) result.lastPost = doc; 
            result.count++;
            return;
      }
   });
   return result;
}

但是我如何页面之后按最新发布日期排序?是否有一种方法可以将查询结果中的doc-id作为另一个的过滤条件(最好是使用一次往返)作为过滤条件?

线程中的帖子数没有限制,所以我有点不愿在这里转达列表功能,当页面大小也可以变化时,将导致最后的帖子完全不显示。

join couchdb reduce
1个回答
1
投票
如果将时间添加为键的第二部分,则可以结合使用endkey,降序和限制来获得基于thread_id的最后N个帖子。

这是我根据您的模式使用一些测试数据编写的MapReduce:

function(doc) { if (doc.type) { if (doc.subject) { emit([doc._id, doc.time], doc.subject); emit([doc._id, 'Z'], doc.subject); } else { emit([doc.thread_id, doc.time], {_id: doc._id}); } } }

'Z'键的奇怪输出是允许您从项目列表的“底部”获得主题。

查询参数看起来像:

?endkey=["thread_id"]&descending=true&limit=6

该限制应为N + 1,其中N是您要回复的帖子数。在结果中,您将拥有帖子文档中的线程主题和_id对象(或您想要的任何对象)。

在此示例中,输出_id对象,因此如果需要完整的帖子,可以将其与include_docs=true一起使用。将您想要的后期文档中的其他任何数据(标题等)扔掉,以使整体索引大小保持较小,并在需要文档全部内容的地方使用include_docs。但是,如果您始终需要完整的后期文档,请在发出时将其输出,因为这样可以使您更快地响应(尽管磁盘上的索引大小较大)。

[此外,如果您需要按最新帖子排序的所有线程的列表,以及每个线程5个帖子,则需要输出[time, thread_id, 'thread'][time, thread_id, 'post']之类的键,并使用_list来收集帖子“在“每个线程文档”下面,因为时间排序将导致线程和帖子在结果中分开。然后可以使用_list功能再次组合/查找它们。但是,执行两个请求可能仍然更容易/更轻松。

© www.soinside.com 2019 - 2024. All rights reserved.