A quick way to start experimenting with Datomic

I need to learn Datalog and Datomic. A quick Youtube search found me this fantastic talk, by Norbert Wójtowicz, with which I can almost feel the needed knowledge start marching into my brain. Now I need to quickly get me a Datomic database to practice with!

A quick way to create a Datomic database, populate, and query it, is to follow the Datomic Getting Started guide. However, using Datomic Cloud for the first time, it takes a while before getting down to writing and reading stuff to and from the database. So here is an even quicker, almost zero-conf, alternative, using Datomic Free and a memory database.

I like to experiment with Clojure things in files in a REPL powered editor. Therefore this mini-guide starts like so:

1. Create a fresh project. I use Leiningen here. But I could have used whatever.

$ lein new datomic-shortcut

Open the project in your favorite Clojure editor and connect to the REPL.

From here on this is almost a replica of the Getting Started guide, but the API is a tad different than the client API used there, so I have made some slight adaptions.

2. Add dependency. This is the latest Datomic Free that I found on Clojars:

[com.datomic/datomic-free "0.9.5697"]

3. Require the Datomic API. The Leiningen project will have the file src/datomic_shortcut/core.clj already created. Select all text in it and replace with this.

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

4. Create the database and the connection. In order to not having to start a transactor or anything, we use a memory database.

(def db-uri "datomic:mem://foo")

  (d/create-database db-uri)
  (def conn (d/connect db-uri)))

I have ”hidden” all database touching things inside (comment ...) forms so that I can load the file in the REPL w/o recreating the database and such. Just evaluate them one by one, top to bottom, regardless if they are inside a comment or not.

5. Add the movie schema to the database.

(def movie-schema [{:db/ident :movie/title
                    :db/valueType :db.type/string
                    :db/cardinality :db.cardinality/one
                    :db/doc "The title of the movie"}

                   {:db/ident :movie/genre
                    :db/valueType :db.type/string
                    :db/cardinality :db.cardinality/one
                    :db/doc "The genre of the movie"}

                   {:db/ident :movie/release-year
                    :db/valueType :db.type/long
                    :db/cardinality :db.cardinality/one
                    :db/doc "The year the movie was released in theaters"}])

  @(d/transact conn movie-schema)
  ;; => {:db-before ...,
  ;;     ...}

6. Add some movies.

(def first-movies [{:movie/title "The Goonies"
                    :movie/genre "action/adventure"
                    :movie/release-year 1985}
                   {:movie/title "Commando"
                    :movie/genre "thriller/action"
                    :movie/release-year 1985}
                   {:movie/title "Repo Man"
                    :movie/genre "punk dystopia"
                    :movie/release-year 1984}])

  @(d/transact conn first-movies)
  ;; => {:db-before ...,
  ;;     ...}


7. Query the titles back out. I’m sorry that I can’t say anything about the query, I need to learn more Datalog first. :smile:

(def all-titles-q '[:find ?movie-title
                    [_ :movie/title ?movie-title]])

  (d/q all-titles-q (d/db conn))
  ;; => #{["Commando"] ["The Goonies"] ["Repo Man"]}

That’s it! Seven is the most magic number, as my youngest son often tells me. I will now spend some more time at this seventh step to get at least some of Norbert’s lesson to stick.


At /r/clojure it was mentioned that there is also Datomic On-Prem, which is pretty easy to download, licence and configure. Here’s the Getting started for that option: https://docs.datomic.com/on-prem/get-datomic.html

It uses the Client API and is ready for you when you outgrow the in-memory database, while the above is using a pretty old version of the Peer API. (I kinda like zero-install, and zero-conf, for a playground like this, but good to know there are options.)

We use datomic-client-memdb for using the Datomic Client API with peer in-memory DBs. You should be able to just add the library to your deps and get started as easily as detailed above. The API is different given it is using the client API.

1 Like

Thanks for the kind words @PEZ! :blush:

The Datomic Free sometimes lags behind the newest features released with regular On-Prem. One other way is to get a license for Datomic Starter Pro (via https://my.datomic.com/account) and follow the instructions for setting up the maven repo credentials for tools.deps/ leiningen/ boot. Then you can have a project dependency for com.datomic/datomic-pro and start up an in-memory database in the REPL (without needing to run a separate transactor).

For anyone looking for the least-resistance approach: an even faster way of getting started with just the query syntax, is to visit http://www.learndatalogtoday.org/ where you can work through the main ideas with an interactive query browser at the bottom of each chapter and not have to install anything.

1 Like