January 14, 2021

Getting Started With Datalog and Datahike

Table of Contents

  1. Add dependencies and create a database
  2. Add Example Data
  3. Basic Queries
    1. Basic query with explicit properties.
    2. Pull all properties
    3. Add a predicate function
    4. Add a second predicate
  4. Transactions
  5. History

Add dependencies and create a database

:dependencies [[org.clojure/clojure "1.10.1"]
               [io.replikativ/datahike "0.3.2"]]

Import Datahike API as d and from export-db for DB introspection and create basic configuration for an in-memory database.

(ns datahike-test.core
  (:require [datahike.api :as d]
            [datahike.migrate :refer [export-db]])
  (:gen-class))

(def cfg {:schema-flexibility :read ;; allow write without explicit schema
          :store {:backend :mem}})  ;; use in-memory database

(d/create-database cfg)

(def conn (d/connect cfg))

Add Example Data

(d/transact conn {:tx-data [{:db/id 4
                             :job "Clojure Fullstack"
                             :position :fullstack-developer
                             :languages #{:javascript :clojure}}
                            {:db/id -1
                             :job "Clojure Backend Developer"
                             :position :backend-developer
                             :languages #{:clojure}}
                            {:db/id -1
                             :job "Javascript Fullstack"
                             :position :fullstack-developer
                             :languages #{:javascript}}]})

Create DB dump for Datoms to a file for introspection

(export-db @conn "./eavt-dump")

#datahike/Datom [4 :job "Clojure Fullstack" 536870914 true]
#datahike/Datom [4 :languages #{:javascript :clojure} 536870914 true]
#datahike/Datom [4 :position :fullstack-developer 536870914 true]

#datahike/Datom [5 :job "Clojure Backend Developer" 536870915 true]
#datahike/Datom [5 :languages #{:clojure} 536870915 true]
#datahike/Datom [5 :position :backend-developer 536870915 true]

#datahike/Datom [6 :job "Javascript Fullstack" 536870916 true]
#datahike/Datom [6 :languages #{:javascript} 536870916 true]
#datahike/Datom [6 :position :fullstack-developer 536870916 true]

Basic Queries

Basic query with explicit properties.

(d/q '[:find ?e ?title ?langs
       :where
       [?e :position ?title]
       [?e :languages ?langs]]
     @conn)

#{[5 :backend-developer #{:clojure}]
  [6 :fullstack-developer #{:javascript}]
  [4 :fullstack-developer #{:javascript :clojure}]}

Pull all properties

Get all the jobs for clojure fullstack. Use the (pull? ?e [*]) to pull all fields of entity ?e and use the ellipsis ... to pull a set of entities instead just of the first one.

(d/q '[:find [(pull ?e [*]) ...]
       :where
       [?e :position ?title]
       [?e :languages ?langs]]
     @conn)

[{:db/id 4,
  :job "Clojure Fullstack",
  :languages #{:javascript :clojure},
  :position :fullstack-developer}
 {:db/id 6,
  :job "Javascript Fullstack",
  :languages #{:javascript},
  :position :fullstack-developer}
 {:db/id 5,
  :job "Clojure Backend Developer",
  :languages #{:clojure},
  :position :backend-developer}]

Add a predicate function

Filter clojure jobs.

(d/q '[:find [(pull ?e [*]) ...]
       :in $ [?l]
       :where
       [?e :position ?title]
       [?e :languages ?langs]
       [(contains? ?langs ?l)]]
     @conn
     [:clojure])

[{:db/id 4,
  :job "Clojure Fullstack",
  :languages #{:javascript :clojure},
  :position :fullstack-developer}
 {:db/id 5,
  :job "Clojure Backend Developer",
  :languages #{:clojure},
  :position :backend-developer}]

Add a second predicate

Filter only the clojure backend jobs.

(d/q '[:find [(pull ?e [*]) ...]
       :in $ [?l ?p]
       :where
       [?e :position ?title]
       [?e :languages ?langs]
       [?e :position ?pos]
       [(contains? ?langs ?l)]
       [(= ?pos ?p)]]
     @conn
     [:clojure :backend-developer])

[{:db/id 5,
  :job "Clojure Backend Developer",
  :languages #{:clojure},
  :position :backend-developer}]

TODO Transactions

  • transaction introspection

TODO History

  • Query history
Tags: Datahike Clojure Datalog