我有一个应用程序需要一个包含一组产品的数据库,其中每个产品都可以有一组表。最终用户应该能够添加新产品并为产品定义新表。因此每个表都有一组由用户指定的列。然后,用户可以使用数据行填充表。每个表只属于一个产品。
最终用户还应该能够在特定时间点(在特定交易时)查看表格。
我如何在Datomic中为此制作模式,以便查询它尽可能高效?
答案 0 :(得分:1)
我会使用4种实体类型:产品,表格,列和行。
产品和表之间的关系最好由:table/product
到一个ref属性处理,但:product/tables
到多个组件引用属性也可以工作(后者不强制执行 - 多对多的关系。)
同样,我会使用:column/table
或:table/columns
属性。我还有一个:column/name
字符串属性,可能还有一个:column/type
枚举属性。
最难的部分是对行进行建模。
一个诱人的解决方案就是每列创建一个属性 - 我实际上认为这是个坏主意,Datomic属性并不适合这种动态使用。特别是,模式属性存储在Peer上的缓存中,并不意味着变大。 (我可能错了,所以如果Datomic团队的某个人能够确认,那就太好了。)
相反,我会有几十个可重复使用的:row/cell-0
,:row/cell-1
,:row/cell-2
等。'单元格位置'所有表共享的属性。每个实际列都将在创建时映射到一个:column/position
属性。
如果行可以有多种数据类型,那就更难了,你必须为每个(类型,位置)对创建一个属性。
然后每行基本上由:row/table
属性和上面的单元格位置属性组成。
这是一个Datalog查询,可让您阅读整个表格
[: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数据库查询表时,上述所有内容才有用。但是将序列化并将它们存储为blob也是完全可以的 - 特别是如果它们很小的话;稍后,你拉出blob,反序列化它,然后你也可以用Datalog查询。如果表格粗略用于此用途,也许你可以用行来做。