This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-10-30
Channels
- # announcements (2)
- # babashka (37)
- # beginners (64)
- # biff (27)
- # cherry (7)
- # cider (19)
- # clj-kondo (10)
- # clojure-austin (4)
- # clojure-doc (18)
- # clojure-europe (72)
- # clojure-nl (1)
- # clojure-norway (13)
- # clojure-uk (5)
- # clojurescript (18)
- # data-science (28)
- # events (5)
- # graalvm (32)
- # hyperfiddle (6)
- # introduce-yourself (1)
- # jobs (4)
- # joyride (16)
- # juxt (6)
- # malli (7)
- # missionary (3)
- # off-topic (18)
- # pathom (15)
- # portal (14)
- # re-frame (14)
- # reitit (5)
- # releases (1)
- # rum (2)
- # sci (1)
- # shadow-cljs (102)
- # spacemacs (3)
- # sql (6)
- # web-security (2)
- # xtdb (10)
Hello everyone I'm following the XTDB tutorial and experimenting a bit with :in clauses I have this query here, which is parameterised on e and item:
(xt/q (xt/db node)
'{:find [name funds stock item]
:where [[e :company-name name]
[e :credits funds]
[e :units/CH4 stock]]
:in [[e item]]}
[:tombaugh-resources :units/CH4])
;; => #{["Tombaugh Resources Ltd." 151 82 :units/CH4]}
However when I try using the item parameter it stops working:
(xt/q (xt/db node)
'{:find [name funds stock item]
:where [[e :company-name name]
[e :credits funds]
[e #_"THIS IS THE ONLY CHANGE ->" item stock]]
:in [[e item]]}
[:tombaugh-resources :units/CH4])
;; => Execution error (IllegalArgumentException) at xtdb.error/illegal-arg (error.clj:12).
;; Query didn't match expected structure
Could anyone explain to me why this doesn't work?
Thank you!It looks like you misunderstand the query structure a little
(xt/q (xt/db node)
'{:find [name funds stock item]
:where [[e :company-name name]
[e :credits funds]
[e item stock]]
:in [[e item]]}
[:tombaugh-resources :units/CH4])
You say you are using the "item" parameter, but that is not what this query does. You seem to think that :in
is doing some kind of binding where it puts :units/CHR
into the item
symbol. That is not what's happening here.
The format for a where block is [<row_symbol> <access_key> <name_to_bind_to>]
. You will pretty much always have e
at the beginning of each row unless you're doing something complicated. But you're supposed to pick the document field you want to bind next and assign it to a symbol. So for example, [e :item stock]
would put the :item
field of the document into the stock
symbol.
You have provided a symbol, which is invalid. It doesn't know how to access the document with that.
It looks like you've gone off the tutorial a little. Notice that the only example of using item
like you are is doing something different
(defn stock-check
[company-id item]
{:result (xt/q (xt/db node)
{:find '[name funds stock]
:where ['[e :company-name name]
'[e :credits funds]
['e item 'stock]]
:in '[e]}
company-id)
:item item})
This is manually quoting everything that isn't item
so that it can evaluate the item
into a keyword argument that we pass in. So we call (stock-check 1 :units/Au)
and that means stock
becomes whatever the value of :units/Au
is in each document.Hey, yep, XT doesn't support parameterised attributes - you need to quote them in (so they're technically different queries)
Hey, thanks for the explanation! My thinking was based on this section of the docs: https://v1-docs.xtdb.com/language-reference/1.24.1/datalog-queries/#_tuple_binding If I understand correctly, you can parameterise with an :in clause, such that the parameters can be used as an entity or value in a :where tuple or as a :find value, but not as the attribute in a :where tuple. Is that right? In which case, why can't I use an :in parameter as an attribute in the :where tuple? I'll read the rest of the tutorial tomorrow so maybe I get it on my own 🤓
No it's actually the opposite. :where
is doing double duty. It's both filtering documents and binding them to names.
All :in
does is let you pass in parameters. But you need to have already bound the names with :where
.
"Ivan"
is matched to first-name
, but first-name
is mapped to :name
from the where clause
When I say :where
is filtering documents, I mean it's making sure the :name
key is present in the document. Then it binds it to first-name
. It is NOT doing any work with "Ivan", that's what :in
is for
> why can't I use an :in parameter as an attribute in the :where tuple? for the same reason you can't use any other logic var in the attribute position of a :where tuple - the engine simply doesn't support it
Alright, I get it now 😄 My mistake was in assuming it was possible to use logic vars in the attribute position of a :where tuple like in datomic. I just had to unlearn that assumption 🤓 Thank you so much for the help :^)