在 Datomic 中查找具有特定属性的最旧和最新实体的日期?
Finding the date of the oldest and newest entity with a certain attribute in Datomic?
假设有一个像这样的 Datomic 模式:
{:db/id #db/id[:db.part/db]
:db/ident :app/createdAt
:db/doc "The date and time when the entity was created (not necessarily the same as tx time)"
: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 :app/type
:db/doc "The type of the entity"
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db.install/_attribute :db.part/db}
并且在应用程序的生命周期中会创建多个此类实体。我有兴趣为某种类型 (:app/type
) 的最旧和最新实体找到 :app/createdAt
instant/date,比如 "type1"。这样的查询在 Datomic 中会是什么样子?
一种简单的方法是使用 Datalog 查询:
[:find (min ?c) (max ?c) :in $ ?type :where
[?e :app/type ?type]
[?e :app/createdAt ?c]]
性能考虑
从 Datomic 0.9.5385 开始,Datalog 引擎将对匹配 [?e :app/type ?type]
子句的实体执行全面扫描;如果有很多这样的实体,这可能会导致许多网络往返存储、对等点的高资源消耗和显着的延迟。
幸运的是,您可以使用 Datomic 的 Optimization of Range Predicates 来限制查询扫描的 datom 数量。例如,要计算最大创建日期,如果您知道至少有一个这样的实体是在 2016 年 8 月之后创建的,您可以调用:
(d/q '[:find (max ?c) . :in $ ?type ?lower-bound :where
[?e :app/createdAt ?c]
[(>= ?c ?lower-bound)]
[?e :app/type ?type]]
db #inst "2016-08")
请注意 Datalog 子句的顺序很重要。
免责声明:本人对Datomic的源码不了解,以上说法仅是个人实验所得。
假设有一个像这样的 Datomic 模式:
{:db/id #db/id[:db.part/db]
:db/ident :app/createdAt
:db/doc "The date and time when the entity was created (not necessarily the same as tx time)"
: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 :app/type
:db/doc "The type of the entity"
:db/valueType :db.type/string
:db/cardinality :db.cardinality/one
:db.install/_attribute :db.part/db}
并且在应用程序的生命周期中会创建多个此类实体。我有兴趣为某种类型 (:app/type
) 的最旧和最新实体找到 :app/createdAt
instant/date,比如 "type1"。这样的查询在 Datomic 中会是什么样子?
一种简单的方法是使用 Datalog 查询:
[:find (min ?c) (max ?c) :in $ ?type :where
[?e :app/type ?type]
[?e :app/createdAt ?c]]
性能考虑
从 Datomic 0.9.5385 开始,Datalog 引擎将对匹配 [?e :app/type ?type]
子句的实体执行全面扫描;如果有很多这样的实体,这可能会导致许多网络往返存储、对等点的高资源消耗和显着的延迟。
幸运的是,您可以使用 Datomic 的 Optimization of Range Predicates 来限制查询扫描的 datom 数量。例如,要计算最大创建日期,如果您知道至少有一个这样的实体是在 2016 年 8 月之后创建的,您可以调用:
(d/q '[:find (max ?c) . :in $ ?type ?lower-bound :where
[?e :app/createdAt ?c]
[(>= ?c ?lower-bound)]
[?e :app/type ?type]]
db #inst "2016-08")
请注意 Datalog 子句的顺序很重要。
免责声明:本人对Datomic的源码不了解,以上说法仅是个人实验所得。