Fork me on GitHub

Hi I have a question. I’m playing with Clara Rules so that I can understand rules engines better. I have 2 queries that look something like this:

(defquery query-1?
  "Returns what is set on Record 1"
  [Record1 (= ?foo foo) (= ?bar bar)])

(defquery query-2?
  "Returns what is set on Record 2"
  [Record2 (= ?baz baz) (= ?oof oof)])
And I want to make a query that returns the aggregate of both the queries. Something like this:
(defquery unified-query?
  "Returns what is set on both Record 1 and Record 2"
  ;; [Record1 (= ?hmm hmm) (= ?huh huh)
  ;; [Record2 (= ?ooh ooh) (= ?aah aah)]]


I’m not sure how to set up that unified query to return both Records. Is that possible? Or do I need a third Record that represents the 2 records together?


I couldn’t find examples of aggregating queries in any of the tutorials I saw, which made me wonder if it’s not something that happens often- it seems like it would be.


Would Record1 and Record2 have anything in common?


(r/defquery q1
   [Rec1 (= ?hmm hmm) (= ?huh huh)]
   [Rec2 (= ?ooh ooh) (= ?ahh ahh)]])
would be the way to query both records, however since the records don’t share anything in common you would end up with a cross product, ex.
(defn test
  (-> (r/mk-session)
      (r/insert (->Rec1 :a 1) (->Rec1 :b 2) (->Rec2 :c 3) (->Rec2 :d 4))
      (r/query q1)))
ends up producing:
({:?hmm :a, :?huh 1, :?ooh :c, :?ahh 3}
 {:?hmm :a, :?huh 1, :?ooh :d, :?ahh 4}
 {:?hmm :b, :?huh 2, :?ooh :c, :?ahh 3}
 {:?hmm :b, :?huh 2, :?ooh :d, :?ahh 4})


or perhaps the less explicit way:

(r/defquery q1
  [Rec1 (= ?hmm hmm) (= ?huh huh)]
  [Rec2 (= ?ooh ooh) (= ?ahh ahh)])
they both behave the same way


I can’t speak for other’s usage of queries, but in our stack it usually ends up boiling down to a single record type that encompasses several pieces of smaller data.


It should also be noted, to my knowledge, anything that is possible in the lhs of a rule should also be possible in a query

👍 6

Yeah, they have nothing in common and I just wanted to squish them together without a cross product. I was getting a cross product, but really wanted to just concat them.


hmm, not sure i am following you there, however perhaps an accumulator or two might be what you are looking for:

(r/defquery q2
  [?rec-1s <- (acc/all) :from [Rec1]]
  [?rec-2s <- (acc/all) :from [Rec2]])
which nets:
({:?rec-1s [#test_queries.Rec1{:hmm :a, :huh 1} #test_queries.Rec1{:hmm :b, :huh 2}],
  :?rec-2s [#test_queries.Rec2{:ooh :c, :ahh 3} #test_queries.Rec2{:ooh :d, :ahh 4}]})
note that this doesn’t have the niceties of the field level binding because of accumulator grouping semantics(and me wanting to avoid that), but instead offers the full records


acc in this context is an alias for clara.rules.accumulators