This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-03-04
Channels
- # announcements (4)
- # asami (38)
- # babashka (20)
- # beginners (188)
- # cider (1)
- # clara (11)
- # clj-kondo (103)
- # cljs-dev (15)
- # cljtogether (1)
- # clojure (138)
- # clojure-australia (5)
- # clojure-europe (33)
- # clojure-france (1)
- # clojure-losangeles (5)
- # clojure-nl (4)
- # clojure-norway (11)
- # clojure-serbia (3)
- # clojure-uk (11)
- # clojurescript (45)
- # community-development (3)
- # conjure (22)
- # core-async (18)
- # datomic (44)
- # defnpodcast (4)
- # deps-new (1)
- # depstar (49)
- # events (2)
- # fulcro (33)
- # girouette (2)
- # honeysql (37)
- # jackdaw (5)
- # jobs-discuss (16)
- # kaocha (3)
- # leiningen (4)
- # lsp (77)
- # malli (55)
- # membrane (4)
- # off-topic (61)
- # polylith (5)
- # quil (5)
- # reagent (33)
- # reitit (12)
- # remote-jobs (1)
- # reveal (4)
- # rewrite-clj (2)
- # sci (16)
- # shadow-cljs (22)
- # sql (1)
- # test-check (27)
- # tools-deps (44)
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.
(r/defquery q1
[]
[:and
[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/fire-rules)
(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 wayI 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
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