Nosql 保存所有文档关系的日志是CouchDB中的反模式吗?

Nosql 保存所有文档关系的日志是CouchDB中的反模式吗?,nosql,couchdb,cloudant,Nosql,Couchdb,Cloudant,当我们返回数据库中要客户端使用的每个文档时,我们还必须向该文档的响应负载添加属性“isInUse”,以指示给定文档是否被其他文档引用 这是必需的,因为引用的文档无法删除,因此在客户端应用程序中,垃圾箱按钮不应显示在其列表条目旁边 因此,基本上我们有一些关系,其中一个文档可以引用另一个链接: { "_id": "factor:1I9JTM97D", "someProp": 1, "otherProp": 2, "defaultBank": <id of some bank d

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

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

因此,基本上我们有一些关系,其中一个文档可以引用另一个链接:

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

问题在于此解决方案是否是反模式,以及潜在的缺点是什么。

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

  • 文档“docInUse:bank”最终可能会频繁更新。Cloudant允许您更新文档,但当您获得数千个修订时,文档大小就变得非常重要,因为所有以前的修订标记都被保留
  • 如果两个进程试图同时更新中心文档,则更新中心文档会引发文档冲突问题。您可以有冲突,但管理冲突是您的应用程序的责任
  • 如果你有很多关系,这个文档可能会变得非常大(我对你的应用了解不够,无法判断)
另一个解决方案是保持您的
银行:
因子:
销售费用:
文档不变,并为每个关系创建文档,例如:

然后,您可以通过使用适当的索引,通过
doc
usedby
的值查询文档,找到“连接”两侧的文档

我还看到了一些实现,其中文档的
\u id
字段包含所有信息:

{
  "_id": "bank:1S36U3FDD:factor:1I9JTM97D"
  "added": "2018-02-28 10:24:22"
}
主键可以帮助您对文档id进行排序,允许您明智地使用
GET/db/\u all\u 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使“关系缓存”保持最新。

我不理解这个问题。我看不出这个头衔和尸体有什么关系。问题是什么还不清楚。试着重新提问,但在问题正文中有一个明确的问题以及设置/解释。对不起,伙计们,我周末出去了,但现在我编辑了这篇文章,为了清晰起见,让我知道是否有改进的余地。你说“以前,我们使用视图和选择器来查询其他文档中的每个文档引用,但事实证明这并不简单。“但不要解释原因。我的第一印象是,点击一个视图将是确定文档是否在其他地方引用的正确方法,但是您的用例可能会有复杂性。您是否可以编辑该问题以更好地解释为什么该方法不适用于您?团队决定在我们可以使用选择器的情况下远离视图(原因是代码的可维护性等)。对于选择器,我们最终使用了复杂的索引以使其具有良好的性能,但是,如果单个文档结构发生变化,并且索引没有相应地更新,那么查询性能就会大幅下降。当然,我们已经准备好了解决方案,可以根据模型更改等情况自动更新索引,这就是为什么它非常重要的原因之一。这只是我们到目前为止的经验,并不是说选择器+索引不是解决问题的方法。哇,只是注意到它似乎在为每个文档类型使用关系文档。基于你提到的原因,这绝对是一个很大的拒绝。我同意不可变的单一关系文档是更好的解决方案。我看到的一个潜在缺点是,如果每个文档都有10个关系,那么数据库中的10个文档中至少有9个是关系文档。(不确定这本身是否是个问题,你)我们不在文档中存储关系的原因是因为它们是双向的,如果我们使用这种方法,我们必须在两个文档中存储信息并保持同步。我不确定您的回答中“关于交易的所有信息”是什么意思。您不需要在两个文档中都存储关系,您可以将其存储在一个文档中,然后在视图中返回两个方向。e、 g.在我上面的例子中
emit(_id,relation.id);emit(relation.id,_id)
就足够了(我简化了一点)。“关于ay交易的所有信息”:例如,对于两个账户之间的转账,在交易文档中存储收件人和发件人账户的金额和信息,就像记账一样。通过汇总每个账户的金额来计算余额,就像银行也会这样做一样。我只是在猜测您的用例是什么,我正在极大地简化。根据您的用例,不同的解决方案可能更好。
{
  "_id": "bank:1S36U3FDD:factor:1I9JTM97D"
  "added": "2018-02-28 10:24:22"
}
{
  "_id":"salesCharge:VDHV2M9I1",
  "relations": [
    { "type": "bank", "id": "bank:M6FXX6UA5" },
    { "type": "whatever", "id": "whatever:xy" }
  ]
}