Thursday, February 13, 2014

Datomic Lookup Refs

Datomic's new lookup refs provide an easy way to identify entities by domain unique identifiers.

Rationale

Datomic supports several approaches to identity, including internal identifiers (entity IDs that are unique within a database) and external identifiers (domain attributes that are designated to be :db.unique/identity).  Lookup refs provide a concise data representation that accords to external ids the powers of internal ids, and can be used interchangeably with internal ids in the Datomic API. This is powerful, since often, e.g. in the front-end of a system or during imports, you already have the external ids in hand. With lookups refs you can often avoid having to incorporate a lookup in application code since the lookup will be done implicitly when resolving the lookup ref (thus the name).

Implementation

A lookup ref is simply a java.util.List containing two elements: a unique attribute and a value for that attribute.  Encoded in edn, a Lookup ref looks like this:

[:org/email "info@datomic.com"]

Lookup refs can be used in the entity API, or in any of the database index APIs.  For example, the following code retrieves an entity:

// Groovy
db.entity([':org/email', 'info@datomic.com'])
;; Clojure
(d/entity db [:org/email "info@datomic.com"])

Lookup refs can also be used to refer to existing entities in transaction data.  This allows updating transactions to specify :db/id directly instead of using a dummy upsert, as shown below:

;; edn transaction data, using temp :db/id and dummy upsert
[{:db/id #db/id[:db.part/user]
  :org/email "info@datomic.com",
  :org/favoriteColor :blue}]

;; edn transaction data, using lookup ref
[{:db/id [:org/email "info@datomic.com"],
  :org/favoriteColor :blue}]

Similarly, they can be used in transactions to build ref relationships.

We expect that lookup refs will expedite a wide variety of use cases, including imports, interactive exploration, and client application development.  

We look forward to your feedback.