请考虑以下文档结构:
线程:
- 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作为另一个的过滤条件(最好是使用一次往返)作为过滤条件?
线程中的帖子数没有限制,所以我有点不愿在这里转达列表功能,当页面大小也可以变化时,将导致最后的帖子完全不显示。
这是我根据您的模式使用一些测试数据编写的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
功能再次组合/查找它们。但是,执行两个请求可能仍然更容易/更轻松。