Reputation: 1339
I'd like to be able to do something like this:
(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)
This gives me what I expect, but it calls "match?" twice per entity:
(datomic.api/q
'[:find ?m
:where [[?e :user/regex-match ?r]
[(user/match? ?e) ?m]
[(user/match? ?e)]
dbconn)
Upvotes: 2
Views: 1541
Reputation: 2413
If you are worried about performance, use:
(->> (d/datoms (d/db conn) :aevt :user/regex-match)
(filter #(user/match? (:v %)))
(map :v))
which uses the datomic.api/datoms API to stream out :user/regex-match
attribute values that match a predicate i.e. user/match?
. This guarantees your predicate function is only executed once (per entity). Note you can replace (map :v)
with (map :e)
to retrieve their entity ids instead.
If you are really worried about performance and are willing to use additional memory to achieve it, use:
(def fast-match? (memoize match?))
(->> (d/datoms (d/db conn) :aevt :user/regex-match)
(filter #(fast-match? (:v %)))
(map :v))
Which creates a memoized version of your function. This version has even stronger performance guarantees since your predicate function will run at most once (i.e. once per each distinct value) and it could give you exceptional performance if your attribute values were part of a finite set.
For a full code sample, see https://gist.github.com/a2ndrade/5651065
Upvotes: 3
Reputation: 10311
The issue seems to be that ?m
gives you the matches, not the entity. You want something like the following:
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"]])
Note that I mocked up the database using clojure collections.
Based on this output, you regex has a subexpression - which is why you probably see it "twice per entity."
I wonder if you might benefit from the Datomic filter
functionality?
Upvotes: 0