我一直在研究Datomic,它看起来非常有趣。尽管似乎有关于Datomic如何在技术上工作的非常好的信息,但我还没有看到如何考虑数据建模。
Datomic中的数据建模有哪些最佳实践?这方面有没有很好的资源?
发布于 2018-04-24 09:43:18
由于Datomic是新的,我的经验很有限,因此不应以任何方式将此答案视为最佳实践。把它作为Datomic的介绍给那些具有关系背景和渴望更高效的数据存储的人。
在Datomic,你为你的域数据模型的实体是具有价值的属性。因为另一个参考实体可以是值的的属性,你可以模拟关系之间的实体简单。
首先看,这与数据在传统关系数据库中建模的方式并不完全相同。在SQL中,表行是实体和具有值的表的列名称属性。甲关系由外键表示值在表格中的一行引用主键价值另一个表行的。
这种相似性很好,因为可以在建模域时勾画出传统的ER图。可以像在SQL数据库中一样依赖关系,但不需要混淆外键,因为这是为你处理的。在Datomic中写入是事务性的,读取是一致的。因此,可以将数据分隔为任何粒度感觉良好的实体,依靠联接来提供更大的图像。对于许多NoSQL商店来说,这是一个很方便的地方,在这些商店中,通常会有大量非规范化实体在更新期间实现一些有用的原子级别。
在这一点上,你有一个良好的开端。但是Datomic比SQL数据库更灵活。
时间本质上是所有Datomic数据的一部分,所以不需要将数据的历史记录作为数据模型的一部分。这可能是Datomic最受关注的一个方面。
在Datomic中,模式不是在SQL所需的“矩形”中严格定义的。也就是说,一个实体1可以拥有任何它需要的属性来满足你的模型。实体不需要具有NULL
或不适用于其的属性的默认值。如果认为合适,可以将属性添加到特定的单个实体。
因此,可以随时改变单个实体的形状,以响应域中的更改(或更改您对域的理解)。所以呢?这与文档存储(如MongoDB和CouchDB)不同。
与Datomic不同的是,可以在所有受影响的实体上自动执行模式更改。这意味着你可以发出一个事务更新所有实体的形状,基于任意域逻辑,写在你的语言 [2],这将不会影响读者提交之前执行。在关系或文档存储空间中,我没有发现任何与这种功能相近的东西。
决定什么定义了Datomic中实体的“类型”。你可以选择明确,并且要求模型中的每个实体都有一个:table
暗示“类型” 的属性。或者实体只需满足每种类型的属性要求即可符合任意数量的“类型”。
例如,模型可能要求:
:name
,:ssn
,:dob
:name
,:title
,:salary
:name
,:address
:id
,:plan
,:expiration
这意味着像我这样的实体:
{:name "Brian" :ssn 123-45-6789 :dob 1976-09-15
:address "400 South State St, Chicago, IL 60605"
:id 42 :plan "Basic" :expiration 2012-05-01}
可以推断为Person
,Resident
而Member
不是Employee
。
Datomic查询在Datalog中表达,并且可以包含用自己的语言表达的规则,引用未存储在Datomic中的数据和资源。可以将数据库函数作为Datomic中的第一类值存储。这些类似于SQL中的存储过程,但可以作为事务内部的值进行操作,也可以用语言编写。这两个功能都可让你以更加以领域为中心的方式表达查询和更新。
最后,面向对象和关系世界之间的阻抗不匹配一直让我感到沮丧。使用功能性,以数据为中心的语言(Clojure)可以帮助解决这个问题,但Datomic希望提供一种持久的数据存储,不需要心理体操从代码到存储。
作为一个例子,从Datomic获取的实体看起来像Clojure(或Java)映射。它可以传递到更高级别的应用程序,而不需要翻译成对象实例或通用数据结构。遍历该实体的关系将会懒惰地从Datomic获取相关实体。但保证它们将与原始查询保持一致,即使面对并发更新。这些实体看起来是嵌套在第一个实体内的普通旧地图。
这使得数据建模更加自然和多,更不用说在我看来是一场斗争。
:id
也是一个属性Employee
?解决方案是将属性组织到名称空间中。所以你会有两个:member/id
和:employee/id
。提前做此事有助于避免以后发生冲突。ALTER TABLE ALTER COLUMN
这里用SQL的说法来谈论。目前,可以使用正确的定义创建替换属性并移动现有数据。
这听起来可怕,但事实并非如此。因为事务是序列化的,所以可以提交一个创建新属性,将数据复制到它,解决冲突并删除旧属性。它将在没有其他事务干扰的情况下运行,并且可以利用本地语言中特定于领域的逻辑来完成这件事。这基本上就是RDBMS在发布后在幕后做的事情ALTER TABLE
,但是将规则命名。发布于 2018-04-24 10:48:35
[:db/add #db/id[:db.part/user] :db/ident :article.type/animal] [:db/add #db/id[:db.part/user] :db/ident :article.type/weapon] [:db/add #db/id[:db.part/user] :db/ident :article.type/candy]
{:db/id #db/id[:db.part/db] :db/ident :article/type :db/valueType :db.type/ref :db/cardinality :db.cardinality/one :db/doc "The type of article" :db.install/_attribute :db.part/db}
datomic.api/entity
以及eid
和多方法,如果nescessary调度类型上分析它们,因为很难让所有属性的一个很好的查询在一些更复杂的架构。https://stackoverflow.com/questions/-100003303
复制相似问题