Architecture CouchDB-每组的前N个文档

Architecture CouchDB-每组的前N个文档,architecture,couchdb,couchbase,Architecture,Couchdb,Couchbase,目前我正在评估CouchDB,我们将在webproject中遇到几个常见的用例 这些用例之一如下所示: 考虑一个包含以下内容的系统(人为示例): 文章 问题 话题 文章和问题可以分配到多个主题 一个主题有自己的页面(想想主题) 从couchdb进行1次查询是否可以同时获得以下两种结果: 关于主题X的最新N篇文章 以及关于主题X的最新N(或M?)个问题 更一般的说法是:我正在寻找一种按类型分组的方法(在本例中,类型为'article'或'question'),并为每个组返回前n个文档,给定

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

这些用例之一如下所示:

考虑一个包含以下内容的系统(人为示例):

  • 文章
  • 问题
  • 话题
文章和问题可以分配到多个主题

一个主题有自己的页面(想想主题)

从couchdb进行1次查询是否可以同时获得以下两种结果:

  • 关于主题X的最新N篇文章
  • 以及关于主题X的最新N(或M?)个问题
更一般的说法是:我正在寻找一种按类型分组的方法(在本例中,类型为'article'或'question'),并为每个组返回前n个文档,给定特定的排序(在本例中,排序是逆时间顺序的),约束到特定的过滤器(在本例中,主题为'X')

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


感谢您提供的任何见解

通过CouchDB的一个查询就可以同时获得这两个信息。尽管不需要reduce函数,但这两个查询都使用map/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
    以获取相反的时间顺序。(注意,“下行”概念上意味着coach从行的“底部”扫描到“顶部”。因此startkey和endkey是相反的。)
  • startkey=[“articles”,“X”,“{}]
    ,因此这是关于X文章,从时间结束开始
  • endkey=[“articles”,“X”,null]
    ,这与关于X以时间开始结束的文章相同
  • limit=N
    ,以减少结果
因此,查询将如下所示(如果需要,请记住对URL进行编码)

没有

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

关于解决办法的思考 CouchDB是为并行查询而设计的,并鼓励并行查询。在制作过程中,我会同时从另一个答案中提出两个问题。(在Javascript中,这非常简单,但任何异步或线程编程语言都可以做到。)

接收两个结果的响应时间将仅为较长结果的响应时间(即,最先完成的结果是“自由的”)。你甚至可以在O(1)空间和O(n)时间中遍历两个响应的行,以合并它们的时间线,这还不错

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

替代解决方案:GeoCoach
Geocooch扩展实际上是一个通用的二维边界框查询引擎。除此之外,显然,地理空间数据还可以用来查询存储为
时间戳
x
严重性
2-space的日志。然而,它目前仍然是CouchDB的一个独立项目,因此我不愿意称之为“CouchDB查询”。

看起来不错,但最终的查询
GET/db/\u design/my\u app/\u view/topic\u parts?descending=true&startkey=[“articles”,“X”,“{}]&endkey=[“articles”,“X”,null]&limit=N
是否只显示前N篇文章?而不是前N篇文章和前N个问题?澄清一下:你在回答问题时说:“有可能通过CouchDB的一个查询同时得到这两个。”。但最终你的查询只会给出“文章”,而不会给出(文章和问题)。有没有关于如何扩展您的回复以包括这些内容的提示?或者事后诸葛亮,这是不可能的?我理解你的问题的意思是,你希望在一个问题中包含每一个要点,而不是同时包含两个要点。请看我的第二个答案。谢谢。我认为这不一定是性能问题,对吗?请求无论如何都会被缓存,等等。我想我只是过于热衷于尝试将它们结合起来,而有时需要多个请求并不是那么糟糕。请注意,我在您的评论之前扩展了我的答案,不确定您是否看到了它。我认为多个请求肯定要付出代价:客户端代码越复杂,出现错误的可能性就越大。一种愤世嫉俗的观点是CouchDB将艰苦的工作外包给了应用程序开发人员。我的感觉是,正如有通用语言和领域特定语言一样,也有通用数据库和领域特定数据库。CouchDB的优势在于简单的HTTP API和复制。所以“成本”是值得的。谢谢你的扩展:我真的错过了。很高兴听到CouchDB确实是为并发查询而设计的。我将使用并发路径(Java和JS)“陈腐”与我们无关,因此没有问题。对一些人来说,这确实是一个好主意,但我们不会去通用电气
GET /db/_design/my_app/_view/topic_parts?descending=true&startkey=["articles","X",{}]&endkey=["articles","X",null]&limit=N