2013-06-19 6 views
12

Dopo aver eseguito una transazione in datomic per inserire un valore, come posso utilizzare il valore restituito della transazione per ottenere gli ID di qualsiasi entità che è stata creata?Ottenere l'ID di un'entità inserita in datomic?

Ecco un esempio del valore di ritorno ottengo dopo un inserimento:

#<[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 ..... 

posso vedere i Riferimenti alla base ... come posso estrarre i loro valori?

risposta

12

Usa d/resolve-tempid. Se dovessi effettuare una transazione con una singola entità, l'operazione :tx-data funzionerebbe ma se la transazione contenesse più di un'entità, non si conoscerà l'ordine in cui compaiono in :tx-data.

Che cosa si dovrebbe fare è dare id temporanei ai tuoi entità (prima di transazioni) utilizzando (d/tempid) o la sua rappresentazione letterale #db/id[:db.part/user _negativeId_] e quindi utilizzare d/resolve-tempid di andare dal vostro ID temporaneo al reale id proposta dal database. Il codice dovrebbe essere simile:

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

Per un codice di esempio completo , vedere questo gist.

+0

Ah dolce, sapevo che ci dovrebbe essere un modo idiomatico di fare le cose. Stavo attualmente limitando i miei approcci a funzioni che garantivano che avrebbero inserito solo un'entità, ma è davvero bello essere in grado di gestire il caso generale. – HaskellMan

+0

È '(d/transact conn [{: db/id" myentity ": some/attr 123}])' equivalente a '(d/tempid" myentity ")'? –

+0

Ho una situazione in cui ho bisogno di conoscere l'id dell'entità prima dell'inserimento dei dati, in quanto ho bisogno di mettere quell'ID da qualche altra parte prima di poter ottenere tutti i dati necessari per l'inserimento (di solito questo avviene tramite transazione in altri database) . Il tempid sarebbe utile per questo. Il fatto che tu possa risolvere un tempid in un vero ID sembra significare che in seguito dovrei cambiare il tempid con il vero id. – CMCDragonkai

6

Ah, ho capito.

ho dovuto Deref la promessa Clojure, e poi sono stato in grado di tirare fuori i valori che volevo:

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

Ha scritto una funzione rapida basata sulla risposta di a2ndrade. La denominazione non è l'ideale e potrei commettere un passo falso idiomatico; i suggerimenti sono molto graditi

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

Esempio utilizzo:

(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

guardando bene, amico! quindi ho ragione a leggere che si dovrebbe aggiungere la partizione alla mappa tx? (da abbinare a: db/id)? – sova

+1

@sova Aggiunto un esempio. Questo risponde alla tua domanda? – deadghost

+0

sì, è fantastico. grazie mille (= – sova

0

The Tupelo Datomic library ha una funzione (td/eids tx-result) per estrarre facilmente l'identità elettroniche create in una transazione. Ad esempio:

; 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) 
    ] 
Problemi correlati