«

Read

Database Values

Datomic maintains the entire history of your data. From this, you can query against a database value as of a particular point in time.

The db API returns the latest database value from a connection.

noslide

(def db (d/db conn))

An analogy with source control is helpful here. A Datomic connection references the entire history of your data, analogous to a source code repository. A database value from db is analogous to checkout.

Pull

If you know an entity id, you can use the pull API to return information about that entity (or recursively about related entities. Better still, if the entity has a unique attribue, you do not even need to knows its entity id. A lookup ref is a two element list of unique attribute + value that uniquely identifies an entity, e.g.

noslide

[:inv/sku "SKU-42"]

The following call pulls the color, type, and size for SKU-42.

(d/pull db
        [{:inv/color [:db/ident]}
         {:inv/size [:db/ident]}
         {:inv/type [:db/ident]}]
        [:inv/sku "SKU-42"])
=> #:inv{:color #:db{:ident :blue}, 
         :size #:db{:ident :large}, 
         :type #:db{:ident :dress}}

Note that the arguments and return value of pull are both just ordinary data structures, i.e. lists and maps.

Query

Storing and retrieving data by unique id is useful, but a database needs also to provide a declarative, logic-based query. Datomic uses Datalog with negation, which has expressive power similar to SQL + recursion.

The following query finds the skus of all products that share a color with SKU-42

noslide

(d/q '[:find ?sku
       :where [?e :inv/sku "SKU-42"]
              [?e :inv/color ?color]
              [?e2 :inv/color ?color]
              [?e2 :inv/sku ?sku]]
     db)
=>
[["SKU-42"] 
 ["SKU-32"] 
  ...]

Note that the arguments and return value of q are both just ordinary data structures, i.e. lists and maps.

In the :where clauses, each list further constrains the results. For each list:

  • the first element matches the entity id
  • the second element matches an attribute
  • the third element matches an attribute's value

Symbols beginning with a question mark are datalog variables. When the same symbol occurs more than once, it causes a join. In the query above

  • ?e joins SKU-42 to its color
  • ?e2 joins to all entities sharing the color
  • ?sku joins all ?e2 entities to their skus

Now we are confident that we can get basic inventory in and out. Just in time, too, because our stakeholders are back with more feature requests.