Fork me on GitHub

I would like to improve this query. First: the link to :tracking/invoice has either no or one reference. Is it possible to express this in the pull syntax? Currently I get a vector of :tracking/invocie. And then I want to filter by :invoice/status. I put the contains? clause, but I think there must be a way how I give a vector of possible matches. I guess with a vector the query will be run faster?

(def xero-orders-tracking
'[:find [(pull ?id [* {:tracking/_invoice [:tracking/tag :tracking/number]}]) ...]
    :in $ 
    [?id :invoice/id _]
    [?id :invoice/type "ACCREC"]
    [?id :invoice/status ?status]
    [(contains? #{"AUTHORISED" "PAID"} ?status)]

Björn Ebbinghaus10:02:26

Additionally: Order matters. Put the most restraining clause first. In this case, it should be [?id :invoice/type "ACCREC"]


Thanks @U4VT24ZM3 So I guess this is how the order of my where clauses should be then:

[?id :invoice/type "ACCREC"]
[?id :invoice/status ?status]
[(contains? #{"AUTHORISED" "PAID"} ?status)]
[?id :invoice/id _]

Braden Shepherdson23:02:07

back-references like :tracking/_invoice can't help but be "many", even if your data happens to have only one, since there's no way to control how many incoming refs there might be.

Braden Shepherdson23:02:52

you'll have to post-process that with (update _ :tracking/invoice first) or similar.

Braden Shepherdson23:02:58

you can probably skip the [?id :invoice/id _] at the start, unless there are entities with :invoice/type and :invoice/status that don't have :invoice/id.

Braden Shepherdson23:02:49

you can express the status constraint as (or [?id :invoice/status "AUTHORIZED"] [?id :invoice/status "PAID"])