2016-10-06 12 views
0

比方說,我有以下Datomic模式:查找:db/txInstant與Datomic中的屬性中定義的日期最接近?

; --- e1 
{:db/id     #db/id[:db.part/db] 
:db/ident    :e1/guid 
:db/unique    :db.unique/identity 
:db/valueType   :db.type/string 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :e1/createdAt 
:db/valueType   :db.type/instant 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :e1/e2s 
:db/valueType   :db.type/ref 
:db/cardinality  :db.cardinality/many 
:db.install/_attribute :db.part/db} 
.. 

; --- e2 
{:db/id     #db/id[:db.part/db] 
:db/ident    :e2/guid 
:db/valueType   :db.type/string 
:db/cardinality  :db.cardinality/one 
:db/unique    :db.unique/identity 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :e2/startedAt 
:db/valueType   :db.type/instant 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
{:db/id     #db/id[:db.part/db] 
:db/ident    :e2/stoppedAt 
:db/valueType   :db.type/instant 
:db/cardinality  :db.cardinality/one 
:db.install/_attribute :db.part/db} 
.. 

我想找到E1 作出與E1相關聯的任何E2的最後交易:db/txInstant其中,e1的:e1/createdAt或E2的:e2/startedAt:e2/stoppedAt小於或等於供應日期(#inst)。我如何在Datomic中構建這樣的查詢?

回答

1

您可以查詢「歷史」數據庫以查找符合您定義的條件的「最大」交易時間。如果需要,您還可以查看哪些屬性從?attr更改。

(d/transact conn [{:db/id  (d/tempid :db.part/user) 
        :e1/guid  (str (d/squuid)) 
        :e1/createdAt #inst "2016-10-21" 
        :e1/e2s  [{:db/id  (d/tempid :db.part/user) 
            :e2/guid  (str (d/squuid)) 
            :e2/startedAt #inst "2016-10-23" 
            :e2/stoppedAt #inst "2016-10-25"}]}]) 


(d/q '[:find (max ?inst) 
     :in $ ?d 
     :where 
     [?e1 :e1/createdAt ?create] 
     [?e1 :e1/e2s ?e2] 
     [?e2 :e2/startedAt ?start] 
     [?e2 :e2/stoppedAt ?stop] 
     [(compare ?d ?create) ?c1] 
     [(compare ?d ?start) ?c2] 
     [(compare ?d ?stop) ?c3] 
     (not [(pos? ?c1)] [(pos? ?c2)] [(pos? ?c3)]) 
     [?e1 ?attr _ ?tx] 
     [?tx :db/txInstant ?inst]] 
    (d/history (d/db conn)) 
    #inst "2016-10-24") 

2016-10-24將給你#inst你辦理你的datoms。 2016-10-26會給你什麼。

UPDATE:

請允許我通過更改架構:

1)E1和E2重新命名爲 「任務」,其中一個任務(E1)可以有多個子任務(E2) 2)保持事務本身的所有時間戳(即createdAt,startedAt,stopped在tx中全部變爲txInstant)。

通過此更改,查詢只是在給定即時(?tc)的情況下查找e1和/或e2(任務及其子任務)的最近(最大)txInstant。

(q '[:find (max ?t) . 
    :in $ ?e ?tc 
    :where 
    (or-join [?tx] 
       ;; parent task created 
       [?e :task/name _ ?tx] 
       ;; subtask started or stopped 
       (and [?e :task/subtask ?s] 
        [?s _ _ ?tx])) 
    [?tx :db/txInstant ?t] 
    [(compare ?tc ?t) ?x] 
    [(>= ?x 0)]] 
    (d/history (db conn)) 
    parent-task1 
    #inst "2016-10-26") 

示例場景:

@(d/transact conn [{:db/id     #db/id[:db.part/db] 
        :db/ident    :task/name 
        :db/valueType   :db.type/string 
        :db/cardinality  :db.cardinality/one 
        :db.install/_attribute :db.part/db} 
        {:db/id     #db/id[:db.part/db] 
        :db/ident    :task/completed 
        :db/valueType   :db.type/boolean 
        :db/cardinality  :db.cardinality/one 
        :db.install/_attribute :db.part/db} 
        {:db/id     #db/id[:db.part/db] 
        :db/ident    :task/subtask 
        :db/valueType   :db.type/ref 
        :db/cardinality  :db.cardinality/many 
        :db.install/_attribute :db.part/db} 
        {:db/id  #db/id[:db.part/tx] 
        :db/txInstant #inst "2016-01-01"}]) 

;; parent task created on 10-21 
(let [p    (d/tempid :db.part/user -1) 
     {tids :tempids} @(d/transact conn [{:db/id  #db/id [:db.part/tx] 
              :db/txInstant #inst "2016-10-21"} 
             [:db/add p :task/name "Parent Task"]])] 
    (def parent-task1 (d/resolve-tempid (db conn) tids p))) 

;; start a subtask on 10-23 
(let [s    (d/tempid :db.part/user -2) 
     {tids :tempids} @(d/transact conn [{:db/id  #db/id [:db.part/tx] 
              :db/txInstant #inst "2016-10-23"} 
             [:db/add s :task/name "subtask 1"] 
             [:db/add parent-task1 :task/subtask s]])] 
    (def subtask1 (d/resolve-tempid (db conn) tids s))) 

;; stop the subtask on 10-25 
@(d/transact conn [{:db/id #db/id [:db.part/tx] 
        :db/txInstant #inst "2016-10-25"} 
        [:db/add subtask1 :task/completed true]]) 

這樣,上面的查詢將在下面的結果:

2016-10-20 => nil 
2016-10-21 => 2016-10-21 
2016-10-22 => 2016-10-21 
2016-10-23 => 2016-10-23 
2016-10-24 => 2016-10-23 
2016-10-25 => 2016-10-25 
2016-10-26 => 2016-10-25 
+0

這幾乎是我之後我,但我想2016-10 -26給我實體的最新db/txInstant而不是「nothing」。還可以調整查詢來適應這種情況嗎? – Johan