Datomic Cheat Sheet Series Queries Part 3 Rules

In this post I work through the creation of rules using the Datomic MusicBrainz sample database. The example queries are grabbed from the Datomic Docs and the Datomic mbrainz sample GitHub pages. If you want to get started with Datomic, check out the first post in the series. If you want to see other queries, then check out part 1 and part 2.

Relationship diagram

Create a database connection

Create an inline database connection

(require '[datomic.api :as d])
(def db-uri "datomic:dev://localhost:4334/mbrainz-1968-1973")
(def conn (d/connect db-uri))
(def db (d/db conn))

Create a database connection as a function

(ns beryllium.core
  (:require [datomic.api :as d]))

(defn new-db []
  (let [db-uri "datomic:dev://localhost:4334/mbrainz-1968-1973"
        conn (d/connect db-uri)
        db (d/db conn)]
    db))

Rules are a named group of clauses that can be used to create reusable logical components that can be slotted into multiple :where clauses. This binds portions of the query's logic at query time.

Create rules

(def rules ' [[(track-name ?e ?t)
              [?e :track/name ?t]]])

(d/q '[:find ?e ?artist-name ?track-name
       :in $ % ?track-name
       :where
       (track-name ?e ?track-name)
       [?e :track/artists]
       [?a :artist/name ?artist-name]] db rules "Can't Find a Reason")

; =>
; #{[17592186149695 "McCully Workshop" "Can't Find a Reason"]
;   [17592186149685 "Love" "Can't Find a Reason"]
;   [17592186149685 "Bakerloo" "Can't Find a Reason"]
;   ...}
(def rules ' [[(track-name ?e ?t)
              [?e :track/name ?t]]])

(d/q '[:find ?e ?track-name ?duration
       :in $ % ?track-name
       :where
       (track-name ?e ?track-name)
       [?e :track/duration ?duration]] db rules "Can't Find a Reason")

; => #{[17592186149695 "Can't Find a Reason" 271506]
;      [17592186149685 "Can't Find a Reason" 270573]}
(def rules ' [[(track-release ?t ?r)
              [?m :medium/tracks ?t]
              [?r :release/media ?m]]])

(d/q '[:find ?title ?album ?year
       :in $ % ?artist-name
       :where
       [?a :artist/name   ?artist-name]
       [?t :track/artists ?a]
       [?t :track/name    ?title]
       (track-release ?t ?r)
       [?r :release/name  ?album]
       [?r :release/year  ?year]] db rules "John Lennon")

;=>
;#{["Yer Blues" "Live Peace in Toronto 1969" 1969]
;  ["Isolation" "John Lennon/Plastic Ono Band" 1970]
;  ["Open Your Box" "Power to the People" 1971]
;  ...}