2017-06-20 58 views
4

Datomic中没有现成的模式特性用于在多对多关系中对子实体进行排序,但这是一个非常普遍的要求。谷歌搜索已经发现了一些解决方案,所以我想在此清点各种需求和解决方案,并希望得到社区的意见。如何在Datomic中实现排序的一对多关系?

可能要求

  • R1:少数孩子的实体(N)(不知道的小/大 门槛应该是什么)
  • R2:大量子实体的
  • R3:单亲儿童
  • R4:多父母子女
  • R5:递归子女,即存储在Datomic中的树

我的特殊使用案例是R1 + R3 + R5,我认为这很常见,但我想尽可能多地列举,以便将来可以成为其他人的有用参考。

问题实体

每个解决方案似乎公顷面临挑战。我能想到的是:

  • P1:保持插入,删除或移动操作的恒定时间操作。已经有建议使用小数来表示“位置”值,以避免在重新排序时更新所有的孩子。
  • P2:支持与订购的多个父亲关系
  • P3:维护存储的位置或边的复杂性订购或订购更改。
  • P4:更改为“位置”属性影响隐含“上次更改”日期子实体时,它实际上并没有改变
  • P5:查询/拉(特别是递归查询)通过包装连接时变得困难实体

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

所有这些研究并没有帮助我找到哪个溶液的澄清度最适合我的树用例,但我倾向于S2。自然,最简单的复杂性是我的目标,但我怀疑所有的解决方案都是复杂的。

问题:你对这个问题有什么经验,你可以分享什么,这将有助于他人决定?正如他们指出的那样,我会在上面添加更多的R,S和P。我(和其他许多人)会真正感谢任何反馈。

A similar question在几年前被问到,但在那里发生的事情并不多。

+0

你确定S2的链接是正确的吗? –

+0

同意,该帖子没有明确说明订单要求。我添加了另一个。 –

回答

0

为了将来的参考,我通过使用带有拉链的Datomic Linked List包装,对我的要求(有序树存储)取得了很好的成功。链表列表中有一些错误,我将尽快将它们修改/部署到clojars。

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

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

如果从这个原型出现其他有用的观察结果,我会发表进一步的意见。

+0

使用zipper/linkedlist的缺点是你不能使用递归数据查询来读取完整的树。这不是一个大问题,因为d/pull是一个便宜的操作,所以每个节点调用一次就很快 –

0

这实际上取决于您的实际使用情况(您可能同时在单个数据库中有多个不同的数据库)。

首先,选择one-to-manymany-to-many之间的父子关系:

  • one-to-many意味着你能坚持额外的属性右转到子实体,避免了额外:db/id:my.domain/guid:ordinal/ref属性花费宝贵的datoms和历史尺寸。
  • 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个元素列表的位置插入单个元素需要10个额外的数据元,在添加新元素之前触摸每10个元素)。

我认为,唯一没什么问题的解决方案是包装儿童(parent-wrapper-child),它会从您身上带走递归拉式,并以其他方式阻碍。

现在回到你的使用情况:儿童
single-parent + recursive queries = idxnext属性。

+0

谢谢米沙,你指出了两个我已经添加到原始问题中的问题以供参考。我将使用https://github.com/dwhjames/datomic-linklist来试用S3,看看它是如何工作的。仍然会欢迎更多的反馈意见,来自其他人的体验报告...... –

+0

谢谢@clojuremostly,这就是我在P1描述中的含义。如果我将:position作为数字,我会这样做,但是,我在链接列表的一半,似乎在工作。我会随时更新。仍然希望听到更多的人与经验报告,以便社区可以相信这是一个平衡的调查什么是有效的调查。 –

+0

哎呀,没有正确阅读。删除了噪音。对不起'回合。 – ClojureMostly

相关问题