将所有文档关系的日志保存为CouchDB中的反模式吗?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将所有文档关系的日志保存为CouchDB中的反模式吗?相关的知识,希望对你有一定的参考价值。
当我们返回数据库中的每个文档以供客户端使用时,我们还必须向该文档的响应有效负载添加属性“isInUse”,以指示给定的文档是否被其他文档引用。
这是必需的,因为无法删除引用的文档,因此不应在客户端应用程序的列表条目旁边显示垃圾桶按钮。
所以基本上我们有关系,文档可以引用另一个链接:
{
"_id": "factor:1I9JTM97D",
"someProp": 1,
"otherProp": 2,
"defaultBank": <id of some bank document>
}
以前我们使用视图和选择器来查询其他文档中的每个文档引用,但事实证明这是非平凡的。
所以我们团队中的某个人现在已经实现了这一点:我们在下面的专用“关系”文档中注册所有关系,并在每次由服务器创建/更新/删除文档时更新它们,以反映任何新的引用或de-引用:
{
"_id": "docInUse:bank",
"_rev": "7-f30ffb403549a00f63c6425376c99427",
"items": [
{
"id": "bank:1S36U3FDD",
"usedBy": [
"factor:1I9JTM97D"
]
},
{
"id": "bank:M6FXX6UA5",
"usedBy": [
"salesCharge:VDHV2M9I1",
"salesCharge:7GA3BH32K"
]
}
]
}
问题是这种解决方案是否是反模式,以及潜在的缺点是什么。
我会说使用单个文档来记录所有其他文档之间的关系可能会有问题,因为
- 文档“docInUse:bank”最终可能会经常更新。 Cloudant允许您更新文档,但是当您进行数千次修订时,文档大小变得无关紧要,因为所有以前的修订令牌都会被保留
- 如果两个进程同时尝试更新文档,则更新中央文档会引发文档冲突问题。你被允许有冲突,但管理它们是你的应用程序,请参阅here
- 如果你有很多关系,这个文件可能会变得非常大(我不太了解你的应用程序来判断)
另一个解决方案是保持您的bank:*
,factor:*
和salesCharge:*
文档相同,并为每个关系创建一个文档,例如
{
"_id": "1251251921251251",
"type": "relationship",
"doc": "bank:1S36U3FDD",
"usedby": "factor:1I9JTM97D"
}
然后,您可以通过使用合适索引的doc
或usedby
的值查询文档,找到“join”两侧的文档。
我也见过实现,文档的_id
字段包含所有信息:
{
"_id": "bank:1S36U3FDD:factor:1I9JTM97D"
"added": "2018-02-28 10:24:22"
}
并且主键有助于为您排序文档ID,允许您明智地使用GET /db/_all_docs?startkey=x&endkey=y
来获取给定银行ID的关系。
如果您需要撤消关系,只需删除文档!
通过在当前实现它的每个文档create / update / delete上构建关系缓存,您基本上是在数据库中手动重新创建索引。这就是我倾向于将其称为反模式的原因。
改进设计的一个好方法是将每个关系存储为Glynn建议的单独文档。
如果您的关注是一致性(我认为可能是这种情况,通过查看您提到的文档类型来判断),请尝试将有关事务的所有信息放入单个文档中。您可以在文档中的一致位置定义关系,因此不需要更新视图:
{
"_id":"salesCharge:VDHV2M9I1",
"relations": [
{ "type": "bank", "id": "bank:M6FXX6UA5" },
{ "type": "whatever", "id": "whatever:xy" }
]
}
然后,您可以保持视图的一致性,并且可以依靠CouchDB使“关系缓存”保持最新。
以上是关于将所有文档关系的日志保存为CouchDB中的反模式吗?的主要内容,如果未能解决你的问题,请参考以下文章