是否将所有文档关系的日志保存为CouchDB中的反模式?

时间:2018-02-23 22:01:38

标签: nosql couchdb cloudant

当我们返回数据库中的每个文档以供客户端使用时,我们还必须向该文档的响应有效负载添加属性“isInUse”,以指示给定的文档是否被其他文档引用。

这是必需的,因为无法删除引用的文档,因此不应在客户端应用程序的列表条目旁边显示垃圾桶按钮。

所以基本上我们有一个关系,文档可以引用另一个链接:

{
  "_id": "factor:1I9JTM97D",
  "someProp": 1,
  "otherProp": 2,
  "defaultBank": <id of some bank document>
} 

以前我们使用视图和选择器来查询其他文档中的每个文档引用,但这被证明是非平凡的。

所以我们团队中的某个人现在已经实现了这一点:我们在下面的专用“关系”文档中注册所有关系,并在每次由服务器创建/更新/删除文档时更新它们,以反映任何新的引用或取消引用:

{
  "_id": "docInUse:bank",
  "_rev": "7-f30ffb403549a00f63c6425376c99427",
  "items": [
    {
      "id": "bank:1S36U3FDD",
      "usedBy": [
        "factor:1I9JTM97D"
      ]
    },
    {
      "id": "bank:M6FXX6UA5",
      "usedBy": [
        "salesCharge:VDHV2M9I1",
        "salesCharge:7GA3BH32K"
      ]
    }
  ]
}

问题在于这种解决方案是否是反模式以及潜在的缺点。

1 个答案:

答案 0 :(得分:1)

我想说使用单个文档来记录所有其他文档之间的关系可能会有问题,因为

  • 文件&#34; docInUse:bank&#34;最终可能会经常更新。 Cloudant允许您更新文档,但是当您进行数千次修订时,文档大小变得无关紧要,因为所有以前的修订标记都被保留
  • 如果两个进程同时尝试更新文档,则
  • 更新中央文档会引发文档冲突问题。您可能会遇到冲突,但管理它们是您应用的责任,请参阅here
  • 如果你有很多关系,这个文件会变得非常大(我对你的应用程序的判断不够了)

另一种解决方案是保留您的bank:*factor:*&amp; salesCharge:*记录相同内容,并为每个关系创建一个文档,例如

{
  "_id": "1251251921251251",
  "type": "relationship",
  "doc": "bank:1S36U3FDD",
  "usedby": "factor:1I9JTM97D"
}

然后,您可以在&#34;加入&#34;的任何一侧找到文件。通过使用合适的索引以docusedby的值查询文档。

我也看到了实施,其中文档的_id字段包含所有信息:

{
  "_id": "bank:1S36U3FDD:factor:1I9JTM97D"
  "added": "2018-02-28 10:24:22"
}

并且主键有助于为您排序文档ID,允许您明智地使用GET /db/_all_docs?startkey=x&endkey=y来获取给定银行ID的关系。

如果您需要撤消关系,只需删除文档!