Datomic table 模型

Datomic table model

我有一个应用程序需要一个包含一组产品的数据库,其中每个产品可以有一组 table。最终用户应该能够添加新产品并为产品定义新的 table。所以每个 table 都有一组由用户指定的列。然后用户可以用数据行填充 tables。每个 table 只属于一个产品。

最终用户还应该能够查看 table 在特定时间点(在特定交易中)的状态。

我将如何在 Datomic 中为此创建一个架构,以便尽可能高效地查询它?

我会选择 4 种实体类型:产品、table、列和行。

产品和 tables 之间的关系最好由 :table/product 一对一 ref 属性处理,但 :product/tables 对多组件 ref 属性也可以工作(后者不强制执行一对多关系)。

同样,我会使用 :column/table:table/columns 属性。我还会有一个 :column/name 字符串属性,也许还有一个 :column/type 枚举属性。

最难的部分是为行建模。

一个诱人的解决方案是只为每列创建一个属性 - 实际上我认为这是个坏主意,Datomic 属性不适用于这种动态用途。特别是,模式属性存储在 Peer 上的缓存中,不会变大。 (我对此可能是错误的,所以如果 Datomic 团队中的人可以确认,那就太好了。)

相反,我会有几十个可重复使用的 :row/cell-0:row/cell-1:row/cell-2 等 'cell position' 属性,这些属性在所有 tables。每个实际列将在创建时通过一对一 :column/position 属性映射到一个。

如果行可以有多种数据类型,那就有点困难了,基本上你必须为每个(类型,位置)对制作一个属性。

然后每一行基本上由一个:row/table属性和上面的单元格位置属性组成。

这是一个数据日志查询,可让您阅读整个 table

[:find ?row ?column-name ?val :in $ ?table :where
 [?column :column/table ?table]
 [?row :row/table ?table]
 [?row ?pos ?val]
 [?column :column/position ?pos]
 [?column :column/name ?column-name]]

请注意,以上所有内容仅在您想使用 Datalog 直接针对您的 Datomic 数据库查询 table 时才有用。但是,序列化您的 table 并将它们存储为 blob 也完全没问题——尤其是当它们很小的时候;稍后,您拉出 blob,将其反序列化,然后您也可以使用 Datalog 进行查询。如果 tables 对于这个用途来说太粗糙了,也许你可以用行来做。