gpt4 book ai didi

couchdb - 在 CouchDB 上建模文档之间的关系?

转载 作者:行者123 更新时间:2023-12-04 02:05:18 25 4
gpt4 key购买 nike

我正在尝试在 CouchDB 中模拟一个相当简单的关系,但我无法确定实现此目的的最佳方法。我希望用户能够创建视频游戏对象列表。我已经使用 "type":"game" 将视频游戏文档存储在数据库中。我希望能够查询列表对象的 ID(通过 View )并取回列表的元数据(标题、创建日期等)和游戏文档的一部分(例如标题和发布日期)。此外,我希望能够向/从列表中添加/删除游戏,而无需下载整个列表文档并将其发回(因此这意味着我不能像我一样简单地将游戏信息存储在列表文档中)最终喜欢支持对同一个列表做出贡献的多个用户,我不想引入冲突。

在阅读 EntityRelationships 上的 CouchDB wiki 后,我确定设置关系文档可能是最好的解决方案。

游戏:

{
"_id": "2600emu",
"type": "game"
}

list :
{
"_id": 123,
"title": "Emulators",
"user_id": "dstaley",
"type": "list"
}

游戏列表关系:
{
"_id": "98765456789876543",
"type": "relationship",
"list_id": 123,
"game_id": "2600emu"
}

但是,据我所知,这不允许我在 一个请求 中获取列表的元数据和游戏的元数据。有什么建议吗?

最佳答案

很好的问题。您确定了使用“规范化”数据模型(具有链接的不同文档类型)是最佳模型的几个非常重要的原因:

  • 您在用户<==> 列表<==> 游戏之间存在多对多关系。
  • 一对多关系很容易在单个文档中表示,该文档为“多”部分使用容器,但它们会变大,并且可能会出现并发冲突。
  • 扩展单文档模型来存储多对多关系是站不住脚的。
  • 一般来说,文档不变性非常适合并发系统。在 CouchDB 中,您完全按照您的说明进行操作,通过存储表示图中边的“一次写入”文档,然后使用二级索引重建您想要的链接部分,并在单个文件中获取您想要的信息API 查询调用。

  • 您也说得对,这里的解决方案是“map-side-join”(从 hadoop 社区借用)。基本上,您希望在 map 输出中使用不同的行来表示不同的信息。然后,您可以使用范围查询 (startkey/endkey) 来查询您需要的 map 结果部分,瞧,您的“连接”表的物化 View 。但是,您在文档中没有找到的一个难题是:

    3.2.3. Joins With Views

    3.2.3.1. Linked Documents

    If your map function emits an object value which has {'_id': XXX} and you query view with include_docs=true parameter, then CouchDB will fetch the document with id XXX rather than the document which was processed to emit the key/value pair.



    都说了。这就是您如何取消引用指向您通过外键存储的链接文档的指针。然后将其与复合键(JS 数组的键)和 view collation rules 的使用结合起来。 .

    以便您的 View 行按以下方式排序:
    ["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_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 不要通配符,这意味着您不必取消对方括号等的引用,以及 include_docs=true选项将跟随指向您用 game_id 指定的外键的指针。在 relationship文档。

    分析:
  • 您使用本质上不可变的文档来存储状态更改,并让数据库为您计算聚合状态。这是一个可爱的大规模模型,也是我们最成功的模式之一。
  • 添加或删除列表非常有效。
  • 高并发下优秀的伸缩特性
  • 在 Cloudant(和 CouchDB v2.0),我们还没有二级索引的“读写一致性”。它在优先级列表中很高,但存在潜在的极端情况,在故障场景或高负载下,您可能看不到主索引和辅助索引之间的即时一致性。长话短说,仲裁用于主索引,但仲裁不是二级索引的可行模型,因此正在开发另一种一致性策略。
  • 关于couchdb - 在 CouchDB 上建模文档之间的关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17684435/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com