Containment Relationships (:db.type/ref
+ :db/isComponent
)
:db/isComponent
is used to specify containment relationships i.e. the composition relation from UML. You can think of it as a "A has B" kind of relation. Modeling part of a simple blog is a clear example:
In Datomic, if you use the :db/isComponent
attribute as part of Article-Comments relationship above, retracting an article will retract all its comments too. For a full code sample, look at the Datomic: containment relationships i.e. db/isComponent gist.
Note there's nothing in Datomic that prevents you from adding the wrong kind of entity to a :db.type/ref
attribute. In the sample above, Datomic would let you add a reference to an "Author" entity (instead of a Comment) without really caring. That's where foreign key constraints come into play.
Foreign key constraints (:db.type/ref
+ database functions)
Datomic defines relationships using the :db.type/ref
attribute but doesn't really enforce anything about them. To use arbitrary foreign key constraints, you need to use database functions instead.
In the Seattle database you mention, :community/orgtype
attributes are supposed to reference only a few allowed enum values (:community.orgtype/*
) but there's actually no enforcement at runtime:
To show how arbitrary foreign key constraints can be implemented in Datomic, I wrote a database function (called add-fk
) that prevents the wrong enum value from ever be associated with :community/orgtype
attributes.
For a full code sample, look at the Datomic: database functions and foreign-key constraints gist. For example, the add-fk
database function behavior is shown below:
;; 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]]