My goal is to use :inputs as a collection input and then return all pages that have all tags. However, with my current query what it is doing is an OR instead of an AND. How can I change this logic?
#+BEGIN_QUERY
{
:title [:h2 "Physical Devices"]
:query [
:find (pull ?p [*])
:in $ [[?tag]]
:where
(page-tags ?p ?tag)
]
:inputs [[[#{"device"}], [#{"homelab"}]]]
}
#+END_QUERY
Only way I can think of is separating everything out.
Think of the query as validating whether βanyβ is true.
So for this logic we have pages device
and homelab
.
Then we check if the page is tagged with any of the pages we put in.
The only way around that would be to change the input to separate values.
And then test those separate.
#+BEGIN_QUERY
{
:title [:h2 "Physical Devices"]
:query [
:find (pull ?p [*])
:in $ ?tag1 ?tag2
:where
(page-tags ?p ?tag1)
(page-tags ?p ?tag2)
]
:inputs [#{"device"} #{"homelab"}]
}
#+END_QUERY
If I understand your use case correctly, this may not be ideal. But it does work.
Yup, if I use both of them it works, but I wanted a way that could handle an arbitrary amount of tags.
In fact, as a concept, I wanted to understand if I could somehow make a query to which I can pass an arbitrary amount of parameters and make the query return something only if it conforms to all instead of any
Thanks a lot for the answer btw! I ended up using pretty much exactly the same you sent.
1 Like
Try double negation:
#+BEGIN_QUERY
{:title [:h2 "Physical Devices"]
:query [
:find (pull ?p [*])
:in $ ?tag-names
:where
[?p :block/tags _]
(not
[?tag :block/name ?tag-name]
[(contains? ?tag-names ?tag-name)]
(not [?p :block/tags ?tag])
)
]
:inputs [#{"device" "homelab"}]
}
#+END_QUERY