Fork me on GitHub
#datomic
<
2024-01-31
>
cch114:01:38

Is it possible to parameterize collection aggregates in a query? I would like to (sample <N> ?x) where N is provided as a parameter to the query. My fallback is to build the query dynamically, but for obvious reasons that's less desireable.

cch115:01:10

And if the answer is to build the query dynamically, I'm banging my head on why these two queries are different: A single result with three values (the goal):

(d/q {:query {:find ['(sample 3 ?tid)]
              :in '[$]
              :where '[[(q '{:find [(min 10 ?exp)]
                             :where [[_ :st.oauth.token/expires-at ?exp]]} $)
                        [[?oldests]]]
                       [?t :st.oauth.token/id ?tid]
                       [(identity ?oldests) [?expires-at ...]]
                       [?t :st.oauth.token/status ?s]
                       [?t :st.oauth.token/expires-at ?expires-at]]}
      :args [db]})
Ten results each with a single tid value (unexpected):
(d/q {:query {:find [('sample 3 '?tid)]
              :in '[$]
              :where '[[(q '{:find [(min 10 ?exp)]
                             :where [[_ :st.oauth.token/expires-at ?exp]]} $)
                        [[?oldests]]]
                       [?t :st.oauth.token/id ?tid]
                       [(identity ?oldests) [?expires-at ...]]
                       [?t :st.oauth.token/status ?s]
                       [?t :st.oauth.token/expires-at ?expires-at]]}
      :args [db]})
Clearly the quoting is the issue -but it seems like they should be equivalent.

favila16:01:18

In your second example

favila16:01:42

('sample 3 '?tid) => ?tid

favila16:01:52

you are invoking the symbol sample

favila16:01:05

with a failed-lookup value of ?tid

favila16:01:26

You want (list 'sample 3 '?tid)

cch117:01:35

Thank you -I'm embarrassed I didn't catch that myself. I'm struggling with understanding the evaluation context of queries -and doubly so with nested subqueries - getting the inner 10 on the min collection aggregate to be parameterized is proving even harder than the outer 3 on the sample. But regardless, invoking a symbol as a fn at that outer layer should have been an obvious fail.

cch117:01:26

That is awesome. I've been looking for something like that without realizing it -and not just for this issue but also when building rules and such in Datalog.

favila17:01:30

Lets you write (let [sample-n 3] (template [:find [(sample ~sample-n ?tid)] …)) without a giant mess of quote-unquote to keep the datalog symbols unqualified

cch117:01:15

Yep. That's a struggle. @U053S2W0V is probably going to keep me from pulling my hair out. Thanks to both of you.

❤️ 1
icemanmelting16:01:53

I am having an issue with a query and wild card patterns:

(d/q {:query '[:find (pull ?page pattern)
                             :in $ ?id pattern
                             :where
                             [?page :page/id ?id]]
                      :args [(d/db conn)
                             id
                             '[*]]})
It gives me an error: Attribute identifier clojure.core/* of class: class java.lang.String does not start with a colon Any idea why it doesn't work? I also tried adding the pattern directly to the pull expression, but I get the exact same issue

icemanmelting16:01:49

Ok, it seems the issue is actually what the message says, the documentation is not clear on this, and you need to use [:] instead of '[*]

favila16:01:11

Still seems wrong that the *gets namespace-qualified somehow

favila16:01:25

pulling using * as a symbol should work

icemanmelting16:01:46

Yeah, I find it odd. If I use * directly, it just complains about clojue_STAR something

icemanmelting16:01:07

this is the only way I found that actually worked

jeroenvandijk09:02:16

I think you need to change pattern into ?pattern ?

icemanmelting09:02:17

No, that wouldn't work, the '?'convention is only for query arguments, patterns don't use that. If I replace the * with a different pattern, it works

jeroenvandijk09:02:41

Ok, i thought it became a query argument because of the usage of :in. But i can be wrong of course

icemanmelting09:02:12

What I mean by query argument, is this '[?page :page/id ?id]'

icemanmelting09:02:33

inside the (pull ….) expression, you can't use '?''

icemanmelting09:02:02

or at least, that's what I have read

icemanmelting09:02:22

but I seem to remember trying that out in another situation, and I got an error because of that

1
favila13:02:15

No ?. There is magic support for pull pattern arguments (that I think this example shows may be slightly broken)

👍 2