This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-08-21
Channels
- # announcements (20)
- # beginners (31)
- # biff (8)
- # cherry (5)
- # cider (4)
- # cljs-dev (1)
- # clojure (26)
- # clojure-australia (2)
- # clojure-europe (16)
- # clojure-spec (10)
- # community-development (8)
- # conjure (1)
- # core-async (1)
- # data-oriented-programming (1)
- # data-science (54)
- # datascript (10)
- # fulcro (1)
- # graalvm (2)
- # malli (5)
- # off-topic (3)
- # pathom (23)
- # rdf (1)
- # re-frame (6)
- # reitit (11)
- # shadow-cljs (6)
- # squint (2)
- # xtdb (33)
[{:db/id 1, :co-ordinate {:x 0, :y 1, :z 2}}, {:db/id 2, :co-ordinate {:x 1, :y 1, :z 2}}]
How would I find all entities with a y co-ordinate of 1? Is there a way I can bind the internals of :co-ordinate
as a part of a query?[:find ?e
:where [?e :co-ordinate ?x] [(= 1 (:y ?x))]]
doesn't work, obviouslyThe issue is that (:y ?x)
is not part of your predicate, and not evaluated. One way to solve this is like so:
(let [conn (d/create-conn)]
(d/transact! conn [{:db/id 1, :co-ordinate {:x 0, :y 1, :z 2}}, {:db/id 2, :co-ordinate {:x 1, :y 1, :z 2}}])
(prn (d/q '{:find [?e ?c]
:where [[?e :co-ordinate ?c]
[(?pred ?c)]]
:in [$ ?pred]}
@conn
#(= 1 (:y %)))))
Though there are other ways to express it which are probably better... the point is just that the arguments to the predicate are not evaluated.=> #{[2 {:x 1, :y 1, :z 2}] [1 {:x 0, :y 1, :z 2}]}
The nicer way to express it would be:
'{:find [?e ?c]
:where [[?e :co-ordinate ?c]
[(get ?c :y) ?y]
[(= 1 ?y)]]}
^^ This evaluates the y
lookup separately and binds it to ?y
which can be used with the predicate =
directly. https://docs.datomic.com/on-prem/query/query.html#function-expressions
I guess I'll find a way to flatten the map into the entity instead
Yup well something like {:db/id 1, :x 0, :y 1, :z 2}
isn't much different, and is easier to query 🙂
or you can make :co-ordinate
a ref instead of a value, either will work.