我一直在寻找到Datomic,它看起来真的很有趣。不过,虽然似乎有very good information on how Datomic works technically,我还没有看到太多的人应该如何看待数据建模。
哪些是在Datomic数据建模的一些最佳做法?是否有关于这个问题的任何好的资源?
由于Datomic是新的,我与它的经验是有限的,这个答案不应该被视为以任何方式的最佳实践。以此代替作为介绍到Datomic对于那些有关系背景和更高效的数据存储中的渴望。
在Datomic,你作为拥有值属性的实体域数据模型。由于另一实体的引用可以是一个属性的值,你可以模型实体简单的关系。
第一眼看上去,这是不是所有的数据是在传统的关系数据库建模的方式不同。在SQL中,表行是实体和表中的列名有值的属性。的关系通过在一个表行引用另一表行的主键值的外键值表示。
这种相似性是好的,因为建模您的域名时,你可以勾勒出你的传统ER图。你可以依靠就像你会在SQL数据库中的关系,而是因为这是为您处理不需要更动外键。在Datomic写入是事务性和你的阅读是一致的。所以,你可以将数据分成在任何粒度感觉对实体,依靠连接到提供更大的图片。这是你失去了很多NoSQL的商店,它是常见的有大的便利,非规范化的实体来实现原子的更新过程中一些有益的水平。
在这一点上,你已经开了个好头。但是Datomic比SQL数据库灵活得多。
时间就是一切Datomic数据的固有部分,所以没有必要具体包括数据的历史数据模型的一部分。这可能是最受关注的Datomic的方面。
在Datomic,你的架构没有硬性由SQL所需的“长方形”定义。也就是说,entity1可以有任何属性,它需要满足你的模型。实体不需要有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,但可以被操纵作为交易的内部数值,也写在你的语言。这些功能都让你表达的多个域为中心的方式查询和更新。
最后,面向对象和关系世界之间的impedance mismatch总是我感到沮丧。使用功能,以数据为中心的语言(Clojure)都与帮助,但Datomic看起来提供一种耐用的数据存储,不需要心理体操从码桥接到存储。
作为一个例子,从Datomic取出的实体外观和行为类似的Clojure(或Java)地图。它可以被传递到上层应用的不翻译成对象实例或一般数据结构。遍历该实体的关系将懒洋洋地获取来自Datomic相关实体。但与保证,他们将与洽原始查询,即使是在并发更新的面貌。而这些实体将显示为嵌套在第一实体内部普通的旧地图。
这使得数据建模更自然,很多,很多在我看来吵架的少。
:id
也是Employee
的属性?解决的办法是你的属性组织到命名空间。所以,你会同时拥有:member/id
和:employee/id
。这样做的提前完成此项有助于避免以后发生冲突。ALTER TABLE ALTER COLUMN
。现在,你可以创建一个正确定义的替代属性和移动现有数据。
这可能听起来很可怕,但事实并非如此。由于交易是序列化,你可以提交一个创建新的属性,复制您的数据,那么,解决冲突,并删除旧的属性。它将运行而不受其他干扰的交易,可以利用特定于域的逻辑在你的母语做的事情。它本质上是一个RDBMS是做什么的,当你发出一个ALTER TABLE
在幕后,但你命名规则。一个很漂亮的回答bkirkbri。我想作一些补充:
[: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]
{:分贝/ ID#分贝/ ID [:db.part /分贝]:分贝/ IDENT:文章/类型:分贝/ VALUETYPE:db.type / REF:分贝/基数:db.cardinality /之一:分贝/ DOC“该类型的文章”:db.install / _attribute:db.part / DB}当你阅读,从查询得到实体的IDS和使用datomic.api/entity
和eid
和多方法,如果nescessary调度类型上分析它们,因为很难让所有属性的一个很好的查询在一些更复杂的架构。