Regex datomic查询-筛选和绑定的函数
我希望能够做到这样:Regex datomic查询-筛选和绑定的函数,regex,clojure,datomic,Regex,Clojure,Datomic,我希望能够做到这样: (defn match? [m] (re-find (re-pattern "so (\\d+)") m)) (datomic.api/q '[:find ?m :where [[?e :user/regex-match ?r] [(user/match? ?e) ?m]] dbconn) 这给了我我所期望的,但它称为“匹配”,每个实体两次: (datomic.api/q '[:find ?m :where [
(defn match? [m] (re-find (re-pattern "so (\\d+)") m))
(datomic.api/q
'[:find ?m
:where [[?e :user/regex-match ?r]
[(user/match? ?e) ?m]]
dbconn)
这给了我我所期望的,但它称为“匹配”,每个实体两次:
(datomic.api/q
'[:find ?m
:where [[?e :user/regex-match ?r]
[(user/match? ?e) ?m]
[(user/match? ?e)]
dbconn)
问题似乎是
?m
提供的是匹配项,而不是实体。您需要以下内容:
user=> (->> (d/q '[:find ?e ?m :in $ :where [?e :user/regex-match ?r]
[(user/match? ?r) ?m]]
[[1 :user/regex-match "so 111"]
[2 :user/regex-match "so 222"]
[3 :user/regex-match "blah 333"]])
(filter #(seq (second %))))
([2 ["so 222" "222"]] [1 ["so 111" "111"]])
注意,我使用clojure集合模拟了数据库
基于此输出,regex有一个子表达式——这就是为什么您可能会看到“每个实体两次”
我想知道你是否能从中受益 如果您担心性能,请使用:
(->> (d/datoms (d/db conn) :aevt :user/regex-match)
(filter #(user/match? (:v %)))
(map :v))
它使用API流式输出与谓词匹配的:user/regex match
属性值,即user/match?
。这保证了谓词函数只执行一次(每个实体)。注意:您可以将(map:v)
替换为(map:e)
,以检索实体ID
如果您确实担心性能,并且愿意使用额外的内存来实现性能,请使用:
(def fast-match? (memoize match?))
(->> (d/datoms (d/db conn) :aevt :user/regex-match)
(filter #(fast-match? (:v %)))
(map :v))
这将创建函数的一个版本。此版本具有更强的性能保证,因为您的谓词函数最多运行一次(即,每个不同的值运行一次),如果您的属性值是有限集的一部分,它可以为您提供优异的性能
有关完整的代码示例,请参见添加(identity?m)而不是调用user/match?这似乎是迄今为止我找到的最好的解决办法。我想知道它在datomic查询中是否惯用?你说“调用<代码>匹配?代码>每个实体两次”是什么意思?你怎么知道?您能否提供一些示例数据(例如Clojure集合)?此外,Clojure正则表达式不要求您转义反斜杠。我不得不把它改成
#“so(\d+)”