2013-06-19 28 views
12

値を挿入するためにdatomicでトランザクションを実行した後、トランザクションの戻り値を使用して作成されたエンティティのIDを取得する方法を教えてください。ここでデータムに挿入されたエンティティのIDを取得しますか?

は私が挿入した後に取得し、戻り値のサンプルです:

#<[email protected]: {:db-before [email protected], :db-after [email protected], 
:tx-data [#Datum{:e 13194139534331 :a 50 
:v #inst "2013-06-19T11:38:08.025-00:00" 
:tx 13194139534331 :added true} #Datum{:e 17592186045436 ..... 

私はどのように私はそれらの値を抽出することができます...基礎となるデータムを見ることができますか?

答えて

12

を使用d/resolve-tempid。単一のエンティティを処理する場合は、:tx-dataを参照してください。トランザクションに複数のエンティティが含まれている場合は、:tx-dataに表示される順序を知ることはできません。あなたは何をすべき

(d/tempid)またはそのリテラル表現#db/id[:db.part/user _negativeId_]のいずれかを使用して(それらを取引する前に)あなたのエンティティに一時的なIDを与えると、データベースによって与えられた実際のIDに一時IDから行くためにd/resolve-tempidを使用しています。このgistを参照して、完全なコードサンプルについて

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

:コードは次のようになります。

+0

ああ、私は物事を行う慣用的な方法があるはずです。私は現在、1つのエンティティのみを挿入することを保証する関数へのアプローチを制限していましたが、一般的なケースを処理できることは本当にうれしいです。 – HaskellMan

+0

'(d/transact conn [{:db/id" myentity ":some/attr 123}])' '(d/tempid" myentity ")'と同等ですか? –

+0

私は、挿入に必要なすべてのデータを取得する前に、そのIDを別の場所に置く必要があるため、データの挿入前にエンティティIDを知る必要がある状況があります(通常、これは他のデータベースのトランザクションによって行われます) 。このためには、一時的な人は役に立つだろうか?あなたが暫定銘柄を現実の銘柄に解決できるという事実は、後で銘柄を実際の銘柄に変更しなければならないことを意味するようです。 – CMCDragonkai

6

ああ、分かりました。

私はClojureの約束をDEREFしなければならなかった、そして私は私が欲しかった値をヤンクすることができました:

(:e (second (:tx-data @(transact! conn query)))) 
1

a2ndradeの回答に基づいてクイック機能を書きました。命名は理想的ではなく、私は慣用的な偽のパスを犯しているかもしれません。提案は大歓迎です。

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

使用例:

(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

見栄えが良い、男!だから私は読んでいる人は、txマップにパーティションを追加しなければならないのでしょうか? (一致する:db/id)? – sova

+1

@sova例を追加しました。それはあなたの質問に答えますか? – deadghost

+0

はい、それは素晴らしいです。ありがとうございます(= – sova

0

The Tupelo Datomic libraryは簡単にトランザクション内で作成されたのEIDを抽出する機能(td/eids tx-result)を持っています。例:

; 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) 
    ] 
関連する問題