如何在Datomic中实现排序到多个关系?

时间:2017-06-20 06:58:25

标签: clojure database-schema datomic

Datomic中没有开箱即用的架构功能,用于在多对多关系中对子实体进行排序,但这是一个非常常见的要求。谷歌搜索已经发现了一些解决方案,所以我想在这里列出需求和解决方案的变化,希望得到社区的评论。

可能的要求

  • R1:小数(N)的子实体(不确定小/大 门槛应该是)
  • R2:大量子实体
  • R3:单亲儿童
  • R4:多亲子女
  • R5:递归子项,即存储在Datomic中的树

我的特定用例是R1 + R3 + R5,我怀疑它很常见,但我想尽可能多地枚举,以便将来可能成为其他人的有用参考。

解决方案

问题

每个解决方案似乎都有挑战。我能想到的是:

  • P1:保持插入,删除或移动操作的恒定时间操作。有人建议对“位置”值使用小数,以避免在重新订购时更新所有子项
  • P2:通过订购支持多个父母关系
  • P3:维护存储订单的位置或边缘的复杂性,如订单或成员资格的变化。
  • P4:更改为“position”属性会影响子实体未实际更改时隐含的“上次更改”日期
  • P5:通过包装器实体进行连接时,查询/拉取(特别是递归查询)会变得很困难

对于我的树用例,我不关心P2和P1不是一个大问题,因为N通常很低

所有这些研究都没有帮助我找清楚哪种解决方案最适合我的树用例,但我倾向于S2。当然,最不复杂的是我的目标,但我怀疑所有解决方案都很复杂。

问题:您对此问题有什么经验吗?您可以分享哪些内容可以帮助其他人做出决定?我们会在指出时添加更多R,S和P。我(以及其他许多人)会非常感谢任何反馈。

几年前曾问过similar question但在那里发生的事情并不多。

3 个答案:

答案 0 :(得分:0)

这实际上取决于您的实际用例(并且您可能同时在单个DB中有几个不同的用例)。

首先,在one-to-manymany-to-many亲子关系中进行选择:

  • one-to-many表示您可以将额外的属性权限放在子实体上,避免在额外的:db/id:my.domain/guid:ordinal/ref属性以及历史记录大小上花费宝贵的数据。< / LI>
  • many-to-many表示您必须有独立的实体来跟踪孩子之间的排序。

此时,你仍然可能想要选择单独的实体,以避免在子实体上弄乱一些latest change date统计/订阅(如果有的话)。在语义上,改变了孩子的顺序意味着父母实体已经改变,而不是儿童实体。

接下来,将recursive pull patterns and queries问题排除在外。如果你选择了attribute on child - 你已经很好了。 如果您使用separate entity,请将有序实体保留在父实体的单独属性中:

{:foo/bars [{:db/id 4}
            {:db/id 2}]
 :foo/bars-order [{:db/id 9 :ordinal/idx 0 :ordinal/ref {:db/id 2}}
                  {:db/id 8 :ordinal/idx 1 :ordinal/ref {:db/id 4}}]} 

缺点是:你需要保持同步以避免孤儿或不明的孩子。

最后,linked listposition values的关系更多的是品味问题。但是,positional values具有更大的tx-data足迹(例如,在10个元素列表的位置0处插入单个元素需要10个额外的数据,在添加新元素的顶部触及每10个元素。)

我认为,唯一的劣质 - 无关紧要的解决方案 - 包装儿童(parent-wrapper-child),它会带走你的递归拉动模式,并以其他方式阻碍。

现在回到你的用例:
  孩子的single-parent + recursive queries = idxnext属性。

答案 1 :(得分:0)

为了将来的参考,我通过使用带有拉链的Datomic Linked List包装器获得了我的要求(有序树存储)的成功。链接列表代码有一些错误,我很快就会将它们/ /修复/部署到clojars。

此解决方案非常简单,并且具有更改操作的恒定时间,因此性能良好。

一个挑战是多个有序的子关系。链表代码假设每个实体有一个有序列表,在我的情况下,我需要1个树子列表,但更多列表用于其他数据。我已经解决了这个问题,但如果您的要求相似,则需要考虑这个问题。

如果其他有用的观察结果来自这个原型,我会发表进一步的评论。

答案 2 :(得分:0)

在我对问题here的答复中,对2019年6月Datomic的新功能有一个针对此问题的新解决方案。