2

我目前正在评估 CouchDB,通过浏览我们将在我们的 web 项目中遇到的几个常见用例。

这些用例之一如下:

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

  • 文章
  • 问题
  • 话题

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

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

是否有可能通过来自 couchdb 的 1 个查询来获得两者:

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

用更通用的术语来说:我正在寻找一种按类型进行分组的方法(在这种情况下, type = 'article' 或 'question' )并为每个组返回给定某种排序的前 n 个文档(在这种情况下排序是按时间倒序的)受限于特定的过滤器(在这种情况下是主题“X”)

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

感谢您的任何见解

4

2 回答 2

1

不。

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

关于解决方法的想法

CouchDB 是为并发查询而设计的,并鼓励并发查询。在生产中,我会同时从我的另一个答案中进行两个查询。(在 Javascript 中,这很容易,但任何异步或线程编程语言都可以做到。)

接收两个结果的响应时间将只是较长结果的响应时间(即首先完成的结果是“空闲”)。您甚至可以遍历两个响应的行,以在 O(1) 空间和 O(n) 时间中合并它们的时间线——还不错!

CouchDB 唯一不能保证的是两个查询都代表完全相同的数据库状态的快照。您提到 Quora,这是现代数据库需求的完美示例。理论上,您不知道这两个查询之间数据库状态发生了多少变化。通常,您不知道一种观点与另一种观点相比是否有意义。在实践中,答案很明显:谁在乎?实际上,仅以毫秒分隔的查询将非常有意义。这就是 CouchDB 非常适合 Web 应用程序的原因,尽管它的功能集受到严格限制。

替代解决方案:GeoCouch

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

于 2011-09-23T14:29:53.173 回答
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 篇文章,这样分解。(注意,这是 CouchDB 中的最小值,而对象是最大的。)null{}

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

因此,查询看起来像这样(如果需要,请记住对 URL 进行编码)。

GET /db/_design/my_app/_view/topic_parts?descending=true&startkey=["articles","X",{}]&endkey=["articles","X",null]&limit=N
于 2011-09-21T21:03:29.400 回答