when writing a
ref attribute, how can we indicate the type? or is that deliberately omitted because datomic (and perhaps clojure) doesn't make use of types, only attributes? in some codebases, i see idents out there called "schema namespaces", and the attr would indicate it is associated with that schema (as would the
refed entity, perhaps). or is it best to have the attr namespaced to match the
i wonder if that last option - matching the attr namespace to the namespace of the
ref'ed entity - is always suitable. for example, you might have a
ref to another
:person entity. then the namespaces wouldn't match.
entities are untyped (they’re just an ID to join facts together), so refs are also untyped
e.g. what makes an entity a “person”?
You could layer a type system on top. a common approach is to add additional attributes to the ref attribute itself that indicates (human or machine-readably) the range (such as type) may have
a more recent feature is to use a pair of entity specs with db/ensure: https://docs.datomic.com/on-prem/schema.html#entity-specs
spec the referent, spec the referred, and add an entity predicate to the referent that asserts that the referred conforms; then add a :db/ensure when you transact changes to the referrer
Is there a canonical direction in modeling parent-child relationships in datomic schemas? For example, consider a schema which represents books and their respective chapters. I see two ways.
1. have a
:book/chapter where book -> chapter. In order to delete the chapter you have retract the chapter entity
and one of the (just realized refs solve this problem, ignore this).
2. have a relationship where chapter -> book. like
db.cardinality/many attributes in the book entity
:chapter/book. This is a
db.cardinality/oneand has the benefit of only needing to retract the entity to delete. My main issue of this is that it seems reversed and for more complicated cases, it is not always clear it is like
:child/parent especially when there is domain specific terminology, Is there a standard convention like
:chapter/parent-bookto denote attributes of this type?
One difference is that you can use
:book/chapter but probably not on
Was just about to say, but don’t you get a many-to-many relation from that
I'm not sure what you mean. https://docs.datomic.com/cloud/schema/schema-reference.html#db-iscomponent
I meant to say, if you make I’m confusing myself, ignore
:book/chapter a ref-many component to a chapter, then pulling`:book/_chapter` on a capter entity also gives a set of books I think. Anyhow — Not particularly important for this discussion
I think you might be right though. The entity API might return a set of "one" book.
Thanks, I did not now about
:db/isComponentand considering my own project nests further with other types and
datascript supports this, it seems like there is only one way to go if I want easy deletions.
(even if there are multiple referents!)
i agree that
isComponent is the best solution here. if in the future you find that components might not fit your data model, you could consider writing transaction functions that handle data cleanup from a business logic perspective.. "when this book is removed from the library, retract chapters and user highlights about those chapters and any reservations for the book". i use a combination of tx fns and a "retraction api" that cleans up the messy parts of the graph, like related unique tuple constraints that no longer make sense when parts of their value are retracted (such as
i've often been tempted to add "reverse component references" between entities just for the sake of data cleanup, but after playing with the idea it felt wrong. components are great.. just saying that they might only get you so far before a tx fn becomes a better option 🙂