2015-10-17 42 views
3

我正在使用Datomic,並希望根據我的查詢從任意數量的時間點拉出整個實體。如果我在查詢執行之前知道這些實例,那麼Datomic docs有一些關於如何從兩個不同的數據庫實例執行查詢的體面示例。但是,我希望查詢確定我需要的「as-of」類型數據庫實例的數量,然後在抽取實體時使用這些實例。這是我到目前爲止有:Datomic:如何查詢查詢中的任意數量的數據庫?

(defn pull-entities-at-change-points [entity-id] 
    (->> 
    (d/q 
     '[:find ?tx (pull ?dbs ?client [*]) 
     :in $ [?dbs ...] ?client 
     :where 
     [?client ?attr-id ?value ?tx true] 
     [(datomic.api/ident $ ?attr-id) ?attr] 
     [(contains? #{:client/attr1 :client/attr2 :client/attr3} ?attr)] 
     [(datomic.api/tx->t ?tx) ?t] 
     [?tx :db/txInstant ?inst]] 
     (d/history (d/db db/conn)) 
     (map #(d/as-of (d/db db/conn) %) [1009 1018]) 
     entity-id) 
    (sort-by first))) 

我試圖找到所有交易,其中一個:client實體的某些屬性發生變化,進而拉動實體,因爲它在這些點的時間存在。行:(map #(d/as-of (d/db db/conn) %) [1009 1018])是我嘗試在兩個特定事務處創建一系列數據庫實例,我知道客戶端的屬性已更改。理想情況下,我想在一個查詢中完成所有這些操作,但我不確定這是否可行。

希望這是有道理的,但讓我知道如果你需要更多的細節。

回答

4

我將拉動調用拆分爲單獨的API調用,而不是在查詢中使用它們。我會保持查詢本身限於獲取感興趣的事務。對於接近一個例子的解決辦法是:

(defn pull-entities-at-change-points 
    [db eid] 
    (let 
    [hdb (d/history db) 
    txs (d/q '[:find [?tx ...] 
       :in $ [?attr ...] ?eid 
       :where 
       [?eid ?attr _ ?tx true]] 
       hdb 
       [:person/firstName :person/friends] 
       eid) 
     as-of-dbs (map #(d/as-of db %) txs) 
    pull-w-t (fn [as-of-db] 
       [(d/as-of-t as-of-db) 
       (d/pull as-of-db '[*] eid)])] 
    (map pull-w-t as-of-dbs))) 

此功能對一個分貝我用玩具的模式內置將返回類似的結果:

([1010 
    {:db/id 17592186045418 
    :person/firstName "Gerry" 
    :person/friends [{:db/id 17592186045419} {:db/id 17592186045420}]}] 
[1001 
    {:db/id 17592186045418 
    :person/firstName "Jerry" 
    :person/friends [{:db/id 17592186045419} {:db/id 17592186045420}]}]) 

的幾點,我會發表評論:

  • 上面的函數需要a database value而不是從環境/全局conn獲取數據庫。
  • 我們爲各個時間t的每個映射拉。
  • using the pull API作爲入口點而不是查詢適用於手頭存在實體和其他信息並且只需要屬性或遍歷引用的情況。
  • 在一個大查詢中完成所有事情的動力在Datomic中並不存在,因爲相關段將在對等緩存中實現。你不是,即使用一個查詢節省往返時間。
  • 收集綁定表格is preferred超過containsleverages query caching
+0

謝謝你的迴應。這非常有幫助! –