我们说我有以下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 或所做的 last 交易的:db/txInstant
到与e1相关联的任何e2,其中e1' s :e1/createdAt
或e2' :e2/startedAt
或:e2/stoppedAt
小于或等于提供的日期(#inst
)。如何在Datomic中构造这样的查询?
答案 0 :(得分:1)
您可以查询"历史" " max"的数据库交易时间符合您定义的标准。如果需要,您还可以检查哪个属性从?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来处理您的数据。 2016-10-26什么都不给你。
<强> 更新: 强>
请允许我通过以下方式更改架构:
1)将e1和e2重命名为&#34; task&#34;任务(e1)可以有多个子任务(e2)
2)在事务本身中保留所有时间戳(即createdAt,startedAt,stoppedAt在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