Wednesday, July 25, 2012

Using the Datomic free edition in a lein based project

Hopefully I can save a few people some time:

I flailed a bit trying to use the first released version yesterday but after updating a new version (datomic-free-0.8.3343) life is good. Download a recent release, and do a local maven install:

mvn install:install-file -DgroupId=com.datomic -DartifactId=datomic-free -Dfile=datomic-free-0.8.3343.jar -DpomFile=pom.xml
Setting a lein project.clj file for this version:
(defproject datomic-test "1.0.0-SNAPSHOT"
  :description "Datomic test"
  :dependencies [[org.clojure/clojure "1.4.0"]
                 [com.datomic/datomic-free "0.8.3343"]])
Do a lein deps and then in the datomic-free-0.8.3343 directory start up a transactor using the H2db embedded database:
cp config/samples/free-transactor-template.properties mw.propreties
bin/transactor mw.propreties
When you run the transactor it prints out the pattern for a connection URI and I used this in a modified version of the Datomic developer's Clojure startup example code:
(ns datomic-test.test.core
  (:use [datomic-test.core])
  (:use [clojure.test]))

(use '[datomic.api :only [q db] :as d])
(use 'clojure.pprint)

(def uri "datomic:free://localhost:4334//news")
(d/create-database uri)
(def conn (d/connect uri))

(def schema-tx (read-string (slurp "data/schema.dtm")))
(println "schema-tx:")
(pprint schema-tx)

@(d/transact conn schema-tx)

;; add some data:
(def data-tx [{:news/title "Rain Today", :news/url "http://test.com/news1", :db/id #db/id[:db.part/user -1000001]}])

@(d/transact conn data-tx)

(def results (q '[:find ?n :where [?n :news/title]] (db conn)))
(println (count results))
(pprint results)
(pprint (first results))

(def id (ffirst results))
(def entity (-> conn db (d/entity id)))

;; display the entity map's keys
(pprint (keys entity))

;; display the value of the entity's community name
(println (:news/title entity))
That was easy. You need to define a schema before using Datomic; here is the simple schema in data/schema.dtm that I wrote patterned on their sample schema (but much simpler!):
[
 ;; news

 {:db/id #db/id[:db.part/db]
  :db/ident :news/title
  :db/valueType :db.type/string
  :db/cardinality :db.cardinality/one
  :db/fulltext true
  :db/doc "A news story's title"
  :db.install/_attribute :db.part/db}

 {:db/id #db/id[:db.part/db]
  :db/ident :news/url
  :db/valueType :db.type/string
  :db/cardinality :db.cardinality/one
  :db/doc "A news story's url"
  :db.install/_attribute :db.part/db}

 {:db/id #db/id[:db.part/db]
  :db/ident :news/summary
  :db/valueType :db.type/string
  :db/cardinality :db.cardinality/one
  :db/doc "Automatically generated summary of a news story"
  :db.install/_attribute :db.part/db}

 {:db/id #db/id[:db.part/db]
  :db/ident :news/category
  :db/valueType :db.type/string
  :db/cardinality :db.cardinality/many
  :db/fulltext true
  :db/doc "Categories automatically set for a news story"
  :db.install/_attribute :db.part/db}

 ]

I hope this saves you some time :-)

8 comments:

Daniel Glauser said...

Thanks for the writeup Mark, you definitely saved me some time! I'm up and running with Datomic. Looking forward to hearing more about what you find.

Mark Watson, author and consultant said...

Thanks Daniel.

I will be using Datomic on a customer's project and before I do that I will do a personal side project as part of my own learning curve. My customer (http://ianeslick.com/) has said that he will blog on some of the more theoretical aspects of data modeling using Datomic, so we can look forward to that :-)

patrickdlogan said...

Has your customer written about the decision to go with datomic? (Assuming it's a done decision.)

I like what I have read about datomic. A rationale for choosing datomic for something categorized as "business critical" would be interesting to see.

Mark Watson, author and consultant said...

Hello Patrick,

That is a good question, but I should not answer for him publicly.

Personally, I would be hesitant. I really like to experiment with new software stacks but when it comes to doing work I get a little conservative: I usually just use a few programming languages and for data stores I tend to stick with PostgreSQL and MongoDB, I prefer deploying to Ubuntu because that is what I am used to, etc.

Oliver George said...

Thanks for the datomic posts. i'm just starting to experiment myself.

what did you put in the transactors property file to change the database name from to news?

I feel like I'm missing a key bit of documentation.

Mark Watson, author and consultant said...

Hello Oliver,

I did not modify the sample property file; I just copied it to the top level datomic-free-0.8.3343 directory as mw.mw.propreties and used it as is. The database name "news" is specified in the connection URI:

(def uri "datomic:free://localhost:4334//news")

-Mark

Steve said...

Mark,

What appeals to you about Datomic as opposed to Postgres or Mongo?


Steve

Mark Watson, author and consultant said...

Hello Steve,

Right now m primary motivation for using Datomic is that a customer chose it for a project.

That said and log term, I believe that being able to access data from any point in time will hit a sweet spot for some types of applications.

I **love** PostgreSQL and MongoDB. They are my default data stores form projects. However I keep an open mind to using alternatives like Datomic, Neo4J, Sesame, AllegroGraph, Hbase, etc.