I'm a newbie to datomic and I'm still trying to figure out how the system has been built. In particular, I don't understand what role :db.part/db plays as it seems to be needed every time a schema is installed. Could somebody shed some light on what this all means?
(require '[datomic.api :as d])
(def uri "datomic:mem://sample")
(d/create-database uri)
(def conn (d/connect uri))
(pprint (seq (d/entity dbval :db.part/db)))
;; =>
;; ([:db/doc "Name of the system partition. The system partition includes the core of datomic, as well as user schemas: type definitions, attribute definitions, partition definitions, and data function definitions."]
;; [:db.install/function #{:db.fn/cas :db.fn/retractEntity}]
;; [:db.install/attribute
;; #{:db/noHistory :db.install/partition :db/cardinality
;; :db.install/attribute :db/index :db/unique :db/fulltext
;; :db/txInstant :db/lang :db/doc :db.install/valueType :db/code
;; :db/isComponent :db/fn :db.install/function :db/valueType :db/ident
;; :fressian/tag}]
;; [:db.install/valueType
;; #{:db.type/uuid :db.type/bigint :db.type/uri :db.type/ref
;; :db.type/keyword :db.type/bytes :db.type/string :db.type/instant
;; :db.type/fn :db.type/long :db.type/bigdec :db.type/boolean
;; :db.type/double :db.type/float}]
;; [:db.install/partition #{:db.part/db}]
;; [:db/ident :db.part/db])
:db.part/db is the partition for schema entities (see the schema docs on partitions). These db.install attributes are used to trigger hooks on the installation of certain entities. That they are asserted of :db.part/db has no special significance (afaik), this is just the convention the Datomic team chose for representing the installation of attributes, etc.
So, e.g., when you submit a transaction like:
[{:db/ident :person/name
:db/cardinality :db.cardinality/one
:db/valueType :db.type/string
:db.install/_attribute :db.part/db
:db/id #db/id[:db.part/db]}]
which is equivalent to (in Clojure now instead of edn):
(let [id (datomic.api/tempid :db.part/db)]
[[:db/add id :db/ident :person/name]
[:db/add id :db/cardinality :db.cardinality/one]
[:db/add id :db/valueType :db.type/string]
[:db/add :db.part/db :db.install/attribute id]])
then Datomic notices you have added a value for :db.part/db's :db.install/attribute, validating that you provided the required attributes for an attribute, and installing the new attribute into the database so you can use it after the transaction.
Similarly, you can use :db.install/_partition :db.part/db to install new partitions. See the docs on Installing an attribute definition and Creating new partitions.
:db.install/valueType could someday be used to install your own custom value types, but this feature is not ready yet. :db.install/function appears to be for internal use. I am not sure of its purpose. The documented way to install database functions is different.
These attributes (except for :db.install/function) are also convenient for queries and inspecting the db. For example, we can pull out the set of all the installed value types, in case we forgot:
user> (:db.install/valueType (datomic.api/entity db :db.part/db))
#{:db.type/uuid :db.type/bigint :db.type/uri :db.type/ref
:db.type/keyword :db.type/bytes :db.type/string :db.type/instant
:db.type/fn :db.type/long :db.type/bigdec :db.type/boolean
:db.type/double :db.type/float}
Or we can write queries over the existing attributes:
user> (datomic.api/q '[:find ?ns (distinct ?attr) :where
[:db.part/db :db.install/attribute ?a]
[?a :db/ident ?attr]
[(namespace ?attr) ?ns]]
db)
[["db" #{:db/noHistory :db/cardinality :db/index :db/unique
:db/fulltext :db/txInstant :db/lang :db/doc
:db/code :db/isComponent :db/fn :db/valueType
:db/ident}]
["db.install" #{:db.install/partition :db.install/attribute
:db.install/valueType :db.install/function}]
["fressian" #{:fressian/tag}]]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With