Getting the id of an inserted entity in datomic?

前端 未结 4 1886
臣服心动
臣服心动 2021-02-19 20:43

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 sam

相关标签:
4条回答
  • 2021-02-19 20:55

    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.

    0 讨论(0)
  • 2021-02-19 21:13

    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
    
    0 讨论(0)
  • 2021-02-19 21:15

    The Tupelo Datomic library has a function (td/eids tx-result) to easily extract the EIDs created in a transaction. For example:

      ; Create Honey Rider and add her to the :people partition
      (let [tx-result   @(td/transact *conn* 
                            (td/new-entity :people ; <- partition is first arg (optional) to td/new-entity 
                              { :person/name "Honey Rider" :location "Caribbean" :weapon/type #{:weapon/knife} } ))
            [honey-eid]  (td/eids tx-result)  ; retrieve Honey Rider's EID from the seq (destructuring)
      ]
    
    0 讨论(0)
  • 2021-02-19 21:17

    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))))
    
    0 讨论(0)
提交回复
热议问题