Si vous utilisez la fonction accumulator de clara-rules, vous pouvez réaliser quelque chose comme une fonction d'agrégation dans SQL, alors essayez-le cette fois. Je vais le voir.
--Utilisez celui de l'espace de noms clara.rules.accumulators
--Min / max / sum etc. sont fournis par défaut
defquery
sur le côté gauche de defrule
[<nom de la variable à lier> <- <accumulateur>: de [<fact> + <constraint>]]
J'ai essayé le code suivant.
(ns clara-rules.accumulator
(:require [clara.rules :refer [fire-rules insert mk-session query defquery]]
[clara.rules.accumulators :as acc]))
(defrecord SomeAmount [id amt])
(defquery test-query
[]
[?largest-amt <- (acc/max :amt) :from [SomeAmount]]
[?total <- (acc/sum :amt) :from [SomeAmount]]
[?grouped <- (acc/grouping-by :id) :from [SomeAmount]]
;;Total by groups
[?grouped-and-summed
<- (acc/grouping-by :id (fn [m]
;;Accepts map key=field for grouping
;;value=seq of maps of records that were grouped
(map (fn [[k seq-of-records]]
{k (reduce + (map :amt seq-of-records))})
m)))
:from [SomeAmount]])
(-> (mk-session)
(insert (->SomeAmount :a 4)
(->SomeAmount :a 8)
(->SomeAmount :b 32)
(->SomeAmount :b 21)
(->SomeAmount :c 1)
(->SomeAmount :c 9))
(fire-rules)
(query test-query))
;; => ({:?largest-amt 32,
;; :?total 75,
;; :?grouped {:a [#clara_rules.accumulator.SomeAmount{:id :a, :amt 4}
;; #clara_rules.accumulator.SomeAmount{:id :a, :amt 8}],
;; :b [#clara_rules.accumulator.SomeAmount{:id :b, :amt 32}
;; #clara_rules.accumulator.SomeAmount{:id :b, :amt 21}],
;; :c [#clara_rules.accumulator.SomeAmount{:id :c, :amt 1}
;; #clara_rules.accumulator.SomeAmount{:id :c, :amt 9}]},
;; :?grouped-and-summed ({:a 12} {:b 53} {:c 10})})
Recommended Posts