考虑以下文档结构:
发
- 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函数在线程中查找最后一篇文章主题取自doc-type 1,最后一篇文档取自doc-type 2。
BTW - 反对链接中的示例,在我的情况下,总是使用第一个帖子创建一个线程(例如,Thread的创建日期将是它的第一个Post的日期)。图:
function(doc){
switch(doc.doc_type){
case 1: emit([doc._id],doc); return;
case 2: emit([doc.thread_id],doc); return;
}
}
减少 对于真实世界的密钥更复杂,因此必须使用适当的组级别。 我也忽略了重新减少的情况,只是为了简单起见。 您可以找到完整图片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作为另一个的过滤条件(最好是使用一次往返)?
一个帖子中的帖子数量没有限制,所以我有点不愿意在这里转发列表功能,当页面大小也可以变化时,会导致最后一个帖子根本没有显示...
任何人
答案 0 :(得分:1)
如果您只是在最后一篇文章或最后五篇文章之后,那么有一种更简单的方法。事实上,你可以完全避免使用减速器。
如果您将时间添加为键的第二部分,则可以使用endkey,descending和limit的组合来根据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。但是,如果您始终需要完整的帖子文档,请将其输出到emit中,这样可以更快地响应(尽管磁盘上的索引大小更大)。
此外,如果您需要按最后一篇文章排序的所有主题的列表以及每个主题的5个帖子,您需要输出[time, thread_id, 'thread']
和[time, thread_id, 'post']
等密钥并使用{{1收集每个线程文档“下”的帖子,因为时间排序会导致线程和帖子在结果中更远。然后可以使用_list
函数再次组合/找到它们。但是,做两个请求可能仍然更容易/更轻。