Как отслеживать идентификатор объекта для материала, который только что был добавлен в БД?

На странице html-сообщения пользователь может вводить различные поля и нажимать «Отправить»,

Мой код router.clj выглядит так

 (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

Это работает хорошо, но я хочу перенаправить пользователя на страницу, которая может показать им загруженный пост. Для этого было бы очень полезно иметь eid объекта, только что совершившего транзакцию.

;; 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}]))

Есть ли способ заставить datomic вернуть eid, как только что-то будет успешно добавлено в БД, или мне следует использовать другой запрос сразу после этого, чтобы убедиться, что он там?


person sova    schedule 05.03.2015    source источник


Ответы (1)


В простых случаях просто удалите ссылку на будущее, возвращаемое d/transact, и используйте :tx-data. Полный пример:

(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))))

В качестве альтернативы вы можете использовать d/resolve-tempid:

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

Как описано в документации Datomic, после отмены ссылки транзакция будет применена транзактор и возвращаемые данные отражают новое значение базы данных.

person justncon    schedule 05.03.2015