收容关系 (:db.type/ref + :db/isComponent)
:db/isComponent 用于指定 containment 关系,即来自 UML 的组合关系。您可以将其视为一种“A 具有 B”的关系。简单博客的建模部分就是一个明显的例子:
在 Datomic 中,如果您使用 :db/isComponent 属性作为上述文章-评论关系的一部分,撤消文章也会撤消其所有 cmets。如需完整的代码示例,请查看Datomic: containment relationships i.e. db/isComponent gist。
注意在 Datomic 中没有任何内容可以阻止您将错误类型的实体添加到 :db.type/ref 属性。在上面的示例中,Datomic 允许您添加对“作者”实体的引用(而不是评论),而无需真正关心。这就是外键约束发挥作用的地方。
外键约束(:db.type/ref + 数据库函数)
Datomic 使用:db.type/ref 属性定义关系,但并没有真正强制执行任何关于它们的事情。要使用任意外键约束,需要改用database functions。
在您提到的西雅图数据库中,:community/orgtype 属性应该只引用少数允许的枚举值 (:community.orgtype/*),但实际上在运行时没有强制执行:
为了展示如何在 Datomic 中实现任意外键约束,我编写了一个数据库函数(称为 add-fk),它可以防止错误的枚举值与 :community/orgtype 属性相关联。
有关完整的代码示例,请查看Datomic: database functions and foreign-key constraints 要点。例如add-fk数据库函数行为如下所示:
;; will succeed
[[:db/add #db/id [:db.part/user] :community/name "15th Ave Community"]
[:add-fk #db/id [:db.part/user] :community/orgtype :community.orgtype/personal]])
;; will fail
[[:db/add #db/id [:db.part/user] :community/name "15th Ave Community"]
[:add-fk #db/id [:db.part/user] :community/orgtype :community.type/email-list]])
;; java.lang.Exception: :community.type/email-list is not one of
;; [[:community.orgtype/community], [:community.orgtype/commercial],
;; [:community.orgtype/personal], [:community.orgtype/nonprofit]]