2014-08-26 1 views
1

Я попадаю в датом и все еще не понимаю. Как создать транзакцию с ссылками на переменное число объектов?Как создать транзакцию, имеющую ссылки на переменное число сущностей?

Например, это создает сделку с дочерним объектом и семьи лица с атрибутом ребенка, который ссылается на новый дочерний объект:

(defn insert-child [id child] 
    {:db/id #db/id id 
    :child/first-name (:first-name child) 
    :child/middle-name (:middle-name child) 
    :child/last-name (:last-name child) 
    :child/date-of-birth {:date-of-birth child}}) 

(defn insert-family [id] 
    (let [child-id #db/id[:db.part/user]] 
    (vector 
    (insert-child child-id 
        {:first-name "Richard" 
        :middle-name "M" 
        :last-name "Stallman"}) 
    {:db/id id 
     :family/child child-id}))) 

(insert-family #db/id[:db.part/user]) 
=> [{:db/id #db/id[:db.part/user -1000012], 
    :child/first-name "Richard", 
    :child/middle-name "M", 
    :child/last-name "Stallman", 
    :child/date-of-birth nil} 
    {:db/id #db/id[:db.part/user -1000013], 
    :family/child #db/id[:db.part/user -1000012]}] 

Примечание Я использовал пусть для child-id. Я не уверен, как написать это, чтобы я мог сопоставить insert-child, имея семейную сущность, которая ссылается на каждую из них.

Я думал об использовании iterate над #db/id[:db.part/user] и количестве потомков, отображающих как результат iterate, так и вектор детей. Кажется, что запутанный и #db/id[:db.part/user] не является функцией для начала итерации.

ответ

3

Вместо использования макрокоманды # db/id [: db.part/user], которая предназначена для файлов EDN и литералов данных, вы должны использовать d/tempid.

Вы могли бы сделать что-то вроде этого (с использованием упрощенных дочерних объектов):

(ns family-tx 
    (:require [datomic.api :refer [q db] :as d])) 

(def uri "datomic:mem://testfamily") 
(d/delete-database uri) 
(d/create-database uri) 
(def conn (d/connect uri)) 

(def schema [ 
       {:db/id (d/tempid :db.part/db) 
       :db/ident :first-name 
       :db/valueType :db.type/string 
       :db/cardinality :db.cardinality/one 
       :db.install/_attribute :db.part/db} 
       {:db/id (d/tempid :db.part/db) 
       :db/ident :last-name 
       :db/valueType :db.type/string 
       :db/cardinality :db.cardinality/one 
       :db.install/_attribute :db.part/db} 
       {:db/id (d/tempid :db.part/db) 
       :db/ident :family/child 
       :db/valueType :db.type/ref 
       :db/cardinality :db.cardinality/many 
       :db.install/_attribute :db.part/db} 
      ]) 
@(d/transact conn schema) 


(defn make-family-tx [kids] 
    (let [kids-tx (map #(into {:db/id (d/tempid :db.part/user)} %) kids) 
     kids-id (map :db/id kids-tx)] 
      (conj kids-tx {:db/id (d/tempid :db.part/user) 
         :family/child kids-id}))) 


(def kids [{:first-name "Billy" :last-name "Bob"} 
      {:first-name "Jim" :last-name "Beau"} 
      {:first-name "Junior" :last-name "Bacon"}]) 

@(d/transact conn (make-family-tx kids)) 

Есть несколько стратегий для этого обсуждаются в Transactions документации, а также (см раздел «Определение Entities»).

+1

Вы можете иметь 'kids-tx' и' kids-id' в одной форме 'let' здесь, так как' let' clojure связывается последовательно, как «let *» Common Lisp, а не параллельно, как CL 'let'. – deadghost

+0

Хороший улов - я пересмотрел пример. –

Смежные вопросы