Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the id of an inserted entity in datomic?

After I run a transaction in datomic to insert a value, how I can use the return value of the transaction to get the ids of any entities that were created?

Here is a sample of the return value I get after an insert:

#<promise$settable_future$reify__4841@7c92b2e9: {:db-before datomic.db.Db@62d0401f, :db-after datomic.db.Db@bba61dfc,
 :tx-data [#Datum{:e 13194139534331 :a 50 
:v #inst "2013-06-19T11:38:08.025-00:00" 
:tx 13194139534331 :added true} #Datum{:e 17592186045436 .....

I can see the underlying datums...how can I extract their values?

like image 486
TG-T Avatar asked Jun 19 '13 11:06

TG-T


3 Answers

Use d/resolve-tempid. If you were to transact a single entity, looking at :tx-data would work but if your transaction contained more than one entity, then you wouldn't know the order in which they appear in :tx-data.

What you should do is give temporary ids to your entities (before transacting them) using either (d/tempid) or its literal representation #db/id[:db.part/user _negativeId_] and then use d/resolve-tempid to go from your temporary id to the real id given by the database. The code would look something like:

(d/resolve-tempid (d/db conn) (:tempids tx) (d/tempid :db.part/user _negativeId_))

For a full code sample, see this gist.

like image 76
a2ndrade Avatar answered Nov 15 '22 00:11

a2ndrade


Ah, figured it out.

I had to deref the Clojure promise, and then I was able to yank out the values I wanted:

 (:e (second (:tx-data @(transact! conn query))))
like image 35
TG-T Avatar answered Nov 15 '22 01:11

TG-T


Wrote a quick function based on a2ndrade's answer. The naming isn't ideal and I may be committing idiomatic faux pas; suggestions are very much welcome.

(ns my.datomic.util
  (:require [datomic.api :as d]))

(defn transact-and-get-id
  "Transact tx and return entity id."
  [conn tx]
  (let [tempid (:db/id tx)
        post-tx @(d/transact conn [tx])
        db (:db-after post-tx)
        entid (d/resolve-tempid db (:tempids post-tx) tempid)]
    entid))

Example usage:

(def my-conn
  (d/connect (str "datomic:sql://datomic?jdbc:postgresql://"
                  "127.0.1:5432/datomic?user=datomic&password=somepw")

(defn thing-tx
  "Create transaction for new thing."
  [name]
  {:db/id (d/tempid :db.part/user)
   :thing/name name})

(transact-and-get-id my-conn (thing-tx "Bob")) ;; => 17592186045502
like image 39
deadghost Avatar answered Nov 15 '22 00:11

deadghost