在CouchDB上建模文档之间的关系?
我试图在CouchDB中建立一个相当简单的关系模型,但我很难确定实现这一点的最佳方法。我希望用户能够创建视频游戏对象的列表。我已经将视频游戏文档存储在数据库中,并带有在CouchDB上建模文档之间的关系?,couchdb,cloudant,Couchdb,Cloudant,我试图在CouchDB中建立一个相当简单的关系模型,但我很难确定实现这一点的最佳方法。我希望用户能够创建视频游戏对象的列表。我已经将视频游戏文档存储在数据库中,并带有“type”:“game”。我希望能够查询列表对象的ID(通过视图),并返回列表的元数据(标题、创建日期等)和游戏文档的部分(例如标题和发布日期)。此外,我希望能够在列表中添加/删除游戏,而无需下载整个列表文档并将其发回(因此这意味着我不能简单地将游戏信息存储在列表文档中),因为我最终希望支持多个用户参与同一列表,并且我不希望引入冲
“type”:“game”
。我希望能够查询列表对象的ID(通过视图),并返回列表的元数据(标题、创建日期等)和游戏文档的部分(例如标题和发布日期)。此外,我希望能够在列表中添加/删除游戏,而无需下载整个列表文档并将其发回(因此这意味着我不能简单地将游戏信息存储在列表文档中),因为我最终希望支持多个用户参与同一列表,并且我不希望引入冲突
在阅读了上的CouchDB wiki之后,我确定设置关系文档可能是最好的解决方案
游戏:
名单:
游戏列表关系:
但是,据我所知,这不允许我在一个请求中获取列表元数据和游戏元数据。有什么建议吗?好问题。您确定了使用“规范化”数据模型(具有链接的不同文档类型)是最佳模型的几个非常重要的原因:
{u id':XXX}
的对象值,并且您使用include\u docs=true
参数查询视图,那么CouchDB将获取id为XXX
的文档,而不是经过处理以发出键/值对的文档
这就说明了一切。这就是如何取消引用指向通过外键存储的链接文档的指针。然后将其与复合键(JS数组键)的使用和
这样,您的视图行将按如下方式排序:
["list_1"], null
["list_1", "game"], {"_id":"game_1234"}
["list_1", "game"], {"_id":"game_5678"}
["list_2"], null
["list_2","game"], {"_id":"game1234"}
["list_3"], null
...
将其与您现有的数据模型结合起来,下面是一些(未经测试的)伪代码,它们应该可以做到这一点:
function(doc) {
if (doc.type=="list") {
//this is the one in the one-to-many
emit( [doc._id]),);
}
else if (doc.type=="relationship") {
//this is the many in the one-to-many
//doc.list_id is our foreign key to the list. We use that as the key
//doc.game_id is the foreign key to the game. We use that as the value
emit( [doc.list_id,'game'], {'_id': doc.game_id});
}
}
最后,您将使用startkey/endkey查询它,以便获得以您感兴趣的list\u id开头的所有行。它看起来像:
curl -g 'https://usr:pwd@usr.cloudant.com/db/_design/design_doc_name/_view/view_name?startkey=["123"]&endkey=["123",{}]&include_docs=true'
-g
选项告诉curl不要使用glob,这意味着您不必取消对方括号等的引用,include_docs=true
选项将跟随指向您在关系
文档中用游戏id
指定的外键的指针
分析:
if(doc.type==“list”){
中的emit不应该是emit(doc.u id,doc)
?或者甚至是emit([doc.u id,0],null)
?我只是有点搞不清楚你的目的是什么,因为有一个不成对的括号和一个没有第二个值的逗号。从视图输出[“list\u 1”],null
,我会选择emit([doc.\u id],null)
。是的,我在这里有点草率。有几件事需要注意。(1)键的结构(emit()方法中的firs参数不需要在每行之间完全相同。这很有用。例如,[“foo”]将在[“foo”,“foo”]之前排序。(2)如果您有一个空条目(例如emit(“foo”);JS运行时将自动在其位置插入null
。抱歉,太草率了。
["list_1"], null
["list_1", "game"], {"_id":"game_1234"}
["list_1", "game"], {"_id":"game_5678"}
["list_2"], null
["list_2","game"], {"_id":"game1234"}
["list_3"], null
...
function(doc) {
if (doc.type=="list") {
//this is the one in the one-to-many
emit( [doc._id]),);
}
else if (doc.type=="relationship") {
//this is the many in the one-to-many
//doc.list_id is our foreign key to the list. We use that as the key
//doc.game_id is the foreign key to the game. We use that as the value
emit( [doc.list_id,'game'], {'_id': doc.game_id});
}
}
curl -g 'https://usr:pwd@usr.cloudant.com/db/_design/design_doc_name/_view/view_name?startkey=["123"]&endkey=["123",{}]&include_docs=true'