sova
sova

Reputation: 5650

How to keep track of the entity id for the stuff that was just added to the db?

On a html-post page a user can input various fields and hit submit,

My router.clj code looks like

 (POST "/postGO" [ post-title post-input post-tags :as request ]
    (def email (get-in request [:session :ze-auth-email]))
      ;; connect to datomic and write in the request
    (dbm/add-ze-post post-title post-input post-tags email) ;; db insert

    {:status 200, 
     :body "successfully added the post to the database", 
     :headers {"Content-Type" "text/plain"}}) ;;generic return page

It works well, but I want to redirect the user afterwards to a page that can show them their uploaded post. To do this, it would be very helpful to have the eid of the entity just transacted.

;; code from my dbm file for playing directly with the database
;; id est: the db transact code
(defn add-ze-blurb [title, content, tags, useremail]
  (d/transact conn [{:db/id (d/tempid :db.part/user),
                     :post/title title,
                     :post/content content,
                     :post/tag tags,
                     :author/email useremail}]))

Is there any way to have datomic return the eid as soon as something is added to the DB successfully, or should I use another query right afterward to make sure it's there?

Upvotes: 1

Views: 88

Answers (1)

justncon
justncon

Reputation: 136

For simple cases, simply deref the future returned by d/transact and use :tx-data. Full example:

(require '[datomic.api :refer [db q] :as d])
(def uri "datomic:mem://test")
(d/create-database uri)

(def conn (d/connect uri))
(def schema [{:db/id (d/tempid :db.part/db)
              :db/ident :foo
              :db/valueType :db.type/string
              :db/cardinality :db.cardinality/one
              :db.install/_attribute :db.part/db}])
@(d/transact conn schema)

(def tempid (d/tempid :db.part/user))
(def tx [{:db/id tempid :foo "bar"}])
(def result @(d/transact conn tx)) ;; 
(def eid (:e (second (:tx-data result))))
(assert (= "bar" (:foo (d/entity (db conn) eid))))

You can alternatively use d/resolve-tempid:

(def eid (d/resolve-tempid (db conn) (:tempids result) tempid))
(assert (= "bar" (:foo (d/entity (db conn) eid))))

As described in the Datomic documentation, after the deref the transaction will have been applied by the transactor and the data returned reflects the new value of the database.

Upvotes: 3

Related Questions