Fork me on GitHub
#xtdb
<
2021-07-07
>
richiardiandrea00:07:30

A million questions I know but is there a better way to work with scalars withing a query? I am doing this at the moment for calculating a percentage - I know I could have a clojure function that does that for me but I was just wondering...

[(/ ?interesting-subsegment-count ?all-subsegment-count)
 ?ratio]
[(float ?ratio)
 ?float-ratio]
[(* 100 ?float-ratio)
 ?percentage]
If I don't do that I get a bunch of "Cannot cast XYZ to java.lang.Number` and similar

refset10:07:23

😄 keep the questions coming! Unfortunately there's no "better" option than the two you've mentioned. There is a way to embed arbitrary Clojure in your Datalog using a custom predicate

(defn inline-clj-pred [f & args]
  (apply (eval f) (vec args)))
...but I strongly discourage using it beyond prototyping(!) https://gist.github.com/refset/a7f86c8a3ad34aea5d20eac0b5720a28

richiardiandrea15:07:13

Ah, yeah I was actually wondering if I could express ranges with inequalities (data like 10 :<= x :< 11) and the use some magic for apply them in a rule 😄

richiardiandrea15:07:05

The other option above probably gets close to it without eval - I'll have to play but thank you!

🙏 2
refset17:07:07

Crux is able to combine range predicates cleverly so you can do [(<= 10 x)][(< x 11)]] with separate clauses and it should be fast

refset17:07:57

beware though that the range predicates are Crux-Datalog specific, so they don't necessarily respect type boundaries, unlike how clojure.core/> and friends behave where you can combine quite a few different types of numbers without worry. You can always specify [(clojure.core/<= 10 x)][(clojure.core/< x 11)]] if needed though

richiardiandrea22:07:16

I feel a bit dirty but here it is 😄

(defn inequalities-satisfied? [inequalities x]
    (let [eval-fn (fn [inequality]
                    (let [[operator y] inequality
                          operator-sym (symbol operator)]
                      (eval `(~operator-sym ~x ~y))))]
      (every? true? (map eval-fn inequalities))))
(inequalities-satisfied? [[:>= 14] [:<= 17]] 17) ;;=> false
Spike = playing around!

richiardiandrea23:07:09

For this one I am representing now classifications as

(crux/submit-tx node [[:crux.tx/put
	                     {:crux.db/id {:measurement-name "ASW Tris"
                                       :classification :classification/severe}
                          :cohesic/type :classification-range
                          :classification/range #{[:>= 18]}}]])
Note that range is the set of my inequalities. Is there a way to tell Crux to leave that :classification/range key alone and assign it to a variable "as is" without decomposing?

richiardiandrea23:07:05

an example query is

(crux/q
   (crux/db node)
   '{:find [(pull ?cs1 [*])]
     :in [?input]
	 :where [[?cs1 :cohesic/type :classification-range]
             [?cs1 :classification/range ?inequalities]
             [(println ?inequalities)]
             ]}
   17)
where I would like to see ?inequalities as #{[:>= 18]} but I see it as [:>= 18] instead

richiardiandrea23:07:28

reading this https://opencrux.com/reference/queries.html#_maps_and_vectors_in_data It seems I will have to create an artificial subkey for that so that the top level won't be decomposed?

refset18:07:32

that's definitely an option, you could also use the semi-official built-in get-attr predicate like this https://github.com/juxt/crux/blob/63e99523b73478490618c99760f3e28e2e1acf33/crux-test/test/crux/query_test.clj#L1077-L1082# (except don't do the destructuring) - I think it will always return a vector with ~undefined ordering. and I can confirm that for you if you want to go down that route

richiardiandrea18:07:03

no ordering should be fine - it's a really a set of inequalities what I am trying to get.

🙂 3
richiardiandrea21:07:04

Given you asked more questions 😄 Does binding results (via :find) currently works in Crux? I tried the Datomic syntax but it does not seem to be working https://docs.datomic.com/cloud/query/query-data-reference.html#find-variables-example This is especially nice for aggregation functions and scalars, for instance when you want to (count ?foo) it's really nice to get a clean number out of the query

refset18:07:06

Crux doesn't currently support the `find-scalar`or `find-coll` parts of the edn Datalog query spec (i.e. . and ..), but things like aggregates (`count` and friends) should definitely work for you, see https://opencrux.com/reference/1.17.1/queries.html#find-aggregate

refset18:07:44

I think you can do some tricks to get a collection back using a subquery, but at the top level you'll always get a set back from Crux's q as things stand today

richiardiandrea18:07:30

ok gotcha thanks Jeremy

👍 3
richiardiandrea23:07:09

For this one I am representing now classifications as

(crux/submit-tx node [[:crux.tx/put
	                     {:crux.db/id {:measurement-name "ASW Tris"
                                       :classification :classification/severe}
                          :cohesic/type :classification-range
                          :classification/range #{[:>= 18]}}]])
Note that range is the set of my inequalities. Is there a way to tell Crux to leave that :classification/range key alone and assign it to a variable "as is" without decomposing?