查找所有缺少特定属性的实体

时间:2019-11-14 20:59:45

标签: datomic

在我的模式中,我具有属性:base/type,该属性应该对于每个创建的实体都存在。为了检查是否确实如此,我正在尝试查找缺少的实体:

[:find [?entities ...]
 :in $ :where
 [(missing? $ ?entities :base/type)]]

不幸的是,这给了我回馈:

Execution error (Exceptions$IllegalArgumentExceptionInfo) at datomic.error/arg (error.clj:57).
:db.error/insufficient-binding [?entities] not bound in expression clause: [(missing? $ ?entities :base/type)]

该查询应如何构建?

2 个答案:

答案 0 :(得分:1)

这是因为您的查询过于笼统。如果使用查询API,则where语句中至少需要一个肯定子句。不过,您可以访问原始索引以获取结果。如果您有足够的RAM,则可以:

(def snapshot (d/db connection)) ; your db snapshot
(def all-datoms (d/datoms snapshot :eavt))
(def base-type-id (:db/id (d/entity snapshot :base/type))  
(def entities (group-by #(.e %) all-datoms))
(def entities-without-base-type (map 
                                  (comp #(into {} %) (partial d/entity snapshot) first) 
                                  (filter (fn [[k l]] 
                                          (empty? (filter #(= base-type-id (.a %)) 
                                        l))) 
                                   entities)))
(def only-relevant-entities (filter #(not (or (:db/ident %) (:db/txInstant %))) entities-without-base-type))

only-relevant-entities

最后一个过滤器是摆脱属性定义和事务(它们也作为datom存储在db中!)。

如果实体太多,则可以使用异步原子API对datom进行分块。

答案 1 :(得分:0)

使用::singer/songs作为示例属性,这是执行查询的方法:

[:find [?entities ...]
 :in $ :where
 [?entities ::singer/songs ?s]
 [(missing? $ ?entities :base/type)]]

不幸的是(在我的回答中)在覆盖整个数据库之前,将需要许多此类查询。因此,另一个使用::song/composers等的查询...