Fork me on GitHub
#xtdb
<
2021-07-05
>
richiardiandrea20:07:36

Hi there, I would I unify against a set? I am trying to use contains? but it does not seem to work ... maybe because I am using it as predicate?

(crux/q
    (crux/db node)
    '{:find [(pull ?range [:crux.db/id {:reference-range-set/_ranges [:crux.db/id :reference-range-set/state]}])]
      :keys [reference-range] 
      :where [[?range :reference-range/classifications ?cs]
              (contains? ?cs :classification/normal)]})

richiardiandrea20:07:03

:reference-range/classifications contains a set

richiardiandrea20:07:07

this is the data

[:crux.tx/put
	                     {:crux.db/id {:measurement-name "ASW"}
                          :cohesic/type :reference-range
                          :reference-range/mean 10
                          :reference-range/standard-deviation 1
                          :reference-range/classifications #{{:classification :classification/borderline
                                                              :range [:< 11]}
                                                             {:classification :classification/mild
                                                              :range [12 14]}
                                                             {:classification :classification/moderate
                                                              :range [15 17]}
                                                             {:classification :classification/severe
                                                              :range [:>= 18]}}}]

richiardiandrea20:07:41

this also returns an empty set of results

(crux/q
    (crux/db node)
    '{:find [(pull ?range [:crux.db/id {:reference-range-set/_ranges [:crux.db/id :reference-range-set/state]}])]
      :keys [reference-range] 
      :where [[?range :reference-range/classifications ?cs]
              [?cs :classification classification/normal]]})

refset21:07:39

Hi - the contains? predicate needs to sit inside a one-element vector (indicating a clause), as in

(crux/q
    (crux/db node)
    '{:find [(pull ?range [:crux.db/id {:reference-range-set/_ranges [:crux.db/id :reference-range-set/state]}])]
      :keys [reference-range] 
      :where [[?range :reference-range/classifications ?cs]
              [(contains? ?cs :classification/normal)]]})

refset21:07:20

this second version you suggested won't work because Crux's Datalog doesn't index beyond the top level of attribute-value (i.e. the maps in the set are opaque values that can't be traversed with triples clauses - you can do things with get / get-in if needed though, or you could given the maps their own IDs and submit them independently)

(crux/q
    (crux/db node)
    '{:find [(pull ?range [:crux.db/id {:reference-range-set/_ranges [:crux.db/id :reference-range-set/state]}])]
      :keys [reference-range] 
      :where [[?range :reference-range/classifications ?cs]
              [?cs :classification classification/normal]]})

richiardiandrea21:07:07

Oh I see now, yeah I was thinking that I was missing something quite fundamental there 😄 Thanks a lot @U899JBRPF

richiardiandrea21:07:06

FWIW that contains? example also returns an empty set

richiardiandrea21:07:39

cause I have to check the :classification key for equality

refset21:07:18

ahh, sorry, yeah I got confused there but something like this would work without having to submit nested docs

(crux/q
    (crux/db node)
    '{:find [(pull ?range [:crux.db/id {:reference-range-set/_ranges [:crux.db/id :reference-range-set/state]}])]
      :keys [reference-range] 
      :where [[?range :reference-range/classifications ?cs]
              [(get ?cs :classification) ?c]
              [(= ?c :classification/normal)]]})

richiardiandrea22:07:11

oh cool yeah I was actually close to that 😄

🙂 2