CouchDB视图:连接和子查询

时间:2010-11-27 18:22:46

标签: couchdb

我把它发布到CouchDB-Users邮件列表中,但我认为我的网络扩大了一点。

[由于stackoverflow的新用户垃圾邮件规则导致链接被破坏:-(]

希望你们中的一个聪明人可以提供帮助 (或者至少有人可以明确告诉我我想要做的事情是不可能的,我会的 我不得不考虑替代方案......我听说MySQL正在接受( - :)。

背景资料: 我在这里设置了一个示例数据库:scoates-test.couchone.com/_utils/database.html?follow / scoates-test.couchone.com/follow

我有两种类型的文件。 type = user and type = asset。

示例用户:scoates-test.couchone.com/_utils/document.html?follow/c988a29740241c7d20fc7974be05f67d

示例资产:scoates-test.couchone.com/_utils/document.html?follow/c988a29740241c7d20fc7974be061d62

用户可以关注其他用户(type =用户文档的“关注”字段)。上面的例子 user(username = bob)是“关注”2个用户:

"following": [
   "c988a29740241c7d20fc7974be05ec54", // username=aaron
   "c988a29740241c7d20fc7974be060bb4" // username=dale
]

资产由特定用户拥有。以上示例资产归c988a29740241c7d20fc7974be061d62所有(用户名= bob)。

希望这是有道理的。

我想请求属于bob正在关注的用户的资产(aaron和dale),以及 我不能把手指放在允许这个的视图代码上。我可以轻松地发出所有资产 属于c988a29740241c7d20fc7974be05f67d。

可以在两个请求中执行此操作。首先,我要问CouchDB c988a29740241c7d20fc7974be05f67d, 然后将以下内容作为“键”发布到返回属于这些键的资产的视图中, 但你会注意到我的type = asset文件也有一个“when”字段,我希望能够 通过发出[doc.owner,doc.when]作为键,然后使用startKey / endKey来排序。 因此,我认为密钥的POST已经发布了。

可以只是加入应用程序端(查询以下键,发出一个请求 这些键中的每一个,然后在应用程序方面排序),但这真的很糟糕地打破了分页(我会 需要为每个后续请求pageSize的限制),并且非常失控 快速(如果用户关注1000个用户,那么每页有10,000个记录)。

这些解决方案都不适合我。我想在 CouchDB中做

我真的很难过。请帮忙。

取值

1 个答案:

答案 0 :(得分:10)

CouchDB视图有一个基本规则,它可以帮助您解决此类问题。

  

查询CouchDB视图会返回零个,一个或多个键值id元组,以便键,值和id从同一文档计算。您可以选择使用提供的id(可能是也可能不是用于计算元组的文档)来请求文档。

如果你考虑一下,它是相当合乎逻辑的:每个元组都是emit()的结果,因此所有发出的数据只能来自一个文档。

在您的特定情况下,您需要使用元组键来包含:

  • 当前用户,因为您只希望该用户可以看到文档
  • 文档的“所有者”,因为您需要按该值排序。
  • 文档的“when”,因为您需要按该值排序。

根据基本规则,您需要一个CouchDB文档来包含所有这些。您当前的架构(“用户”文档中的当前用户和文档所有者,文档所有者以及何时在“文档”文档中)未将所需数据汇集在一起​​,因此您需要对其进行更改。

我的建议是使用具有以下结构的“共享”文档:

{ 
   owner : 'id-of-aaron', 
   followers : [ 'id-of-bob', 'id-of-mike', 'id-of-melissa' ],
   docs : {
     'id-of-doc-1' : '2010-09-08',
     'id-of-doc-2' : '2010-09-07',
     'id-of-doc-3' : '2010-11-27'
   }
}

每当用户关注/取消关注所有者或所有者添加或删除文档时,您都需要更新此结构。从那里,你可以简单地发出:

for (var docid in doc.docs) 
  for (var i in doc.followers) {
    emit ([doc.followers[i], doc.owner, doc.docs[docid]], { _id : docid });
  }
}