CouchDB - 每个组的前N个文档

时间:2011-09-21 20:14:40

标签: architecture couchdb couchbase

我现在正在评估CouchDB,我们将在我们的webproject中遇到几个常见的用例。

其中一个用例如下:

考虑一个包含(人为例子)的系统:

  • 制品
  • 问题
  • 主题

文章和问题可以分配给多个主题。

主题有自己的页面(想想http://www.quora.com主题)。

来自couchdb的1个查询是否可以同时获取:

  • 关于主题X的最新N篇文章
  • 和关于主题X的最新N(或M?)问题

在更通用的术语中:我正在寻找一种按类型进行分组的方法(在这种情况下,类型='article'或'question'),并且对于每个组,返回给出一定的前n个文档sort(在这种情况下,sort是反向时间顺序)约束到特定的过滤器(在这种情况下是主题'X')

从我读过的内容来看,从性能的角度来看,并行执行多个couchdb查询通常并不是什么大不了的事,但我只是好奇这个(对于我们经常使用的)用例是否可以在一个请求中完成。

感谢您的任何见解

2 个答案:

答案 0 :(得分:1)

没有

CouchDB视图是一维的。对于给定的主题,最新的文章和最新的问题是二维查询,因此在一个HTTP请求中是不可能的。

关于解决方法的想法

CouchDB的架构是为了鼓励并发查询。在制作中,我会同时从我的其他答案中提出两个问题。 (在Javascript中,这非常简单,但任何异步或线程编程语言都可以做到。)

接收两个结果的响应时间仅为较长结果的响应时间(即,首先完成的响应时间为“空闲”)。您甚至可以遍历两个响应的行,以在O(1)空间和O(n)时间内合并它们的时间轴 - 不是太糟糕!

CouchDB唯一不保证的是两个查询都代表完全相同的数据库状态的快照。您提到Quora,这是现代数据库要求的完美示例。 理论上,您不知道这两个查询之间有多少数据库状态发生了变化。一般来说,你不知道一个观点与另一个观点相比是否有意义。 在实践中,答案是显而易见的:谁在乎?以毫秒为单位的查询实际上将完美地结合在一起。这就是为什么CouchDB非常适合网络应用程序,尽管功能设置受到严格限制。

替代解决方案:GeoCouch

GeoCouch扩展实际上是一个通用的二维边界框查询引擎。此外,显然,地理空间数据,例如,它可以用于查询存储为timestamp x severity 2空间的日志。但是它目前仍然是CouchDB的一个独立项目,所以我不愿意将其称为“CouchDB查询”。

答案 1 :(得分:0)

来自CouchDB的1个查询可以同时获得两者。两个查询都使用map / reduce查询,但您不需要reduce函数。

您需要视图行为键具有[$type, $topic, $timestamp]对:

["article" , "money", "2011-09-21T20:50:29.819Z"]
["article" , "shoes", "2011-09-21T20:30:29.819Z"]
["article" , "shoes", "2011-09-21T20:50:29.819Z"]
["question", "grits", "2011-01-13T20:30:18.123Z"]
["question", "money", "2011-09-20T20:30:18.123Z"]

此功能可能会这样做:

function(doc) {
    // _design/my_app/_view/topic_parts
    var key;

    if(doc.type && doc.parent_topic && doc.created_at) {
        // Looks good, emit it into the view.
        key = [doc.type, doc.parent_topic, doc.created_at];
        emit(key, doc);
    }
}

要查找最新的N行(无论是文章还是问题),您基本上需要按降序排列[$type, $topic, *]的行。例如,对于主题 X 的最新 N篇文章,就会出现这种情况。 (请注意,null是CouchDB中的最小值,对象{}是最大值。)

  • descending=true获得反向时间顺序。 (注意“降序”在概念上意味着沙发正在从行的“底部”扫描到“顶部”。所以 startkey和endkey是相反的。)
  • startkey=["articles","X",{}],所以这是文章关于 X 从时间结束开始
  • endkey=["articles","X",null],这与 X 相同 X 以时间开头结束
  • limit=N,将结果修剪下来

因此查询将如下所示(请记住在必要时对URL进行编码)。

GET /db/_design/my_app/_view/topic_parts?descending=true&startkey=["articles","X",{}]&endkey=["articles","X",null]&limit=N