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 对于这个用途来说太粗糙了,也许你可以用行来做。
我有一个应用程序需要一个包含一组产品的数据库,其中每个产品可以有一组 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 对于这个用途来说太粗糙了,也许你可以用行来做。