diff --git a/project.clj b/project.clj index e443404..310b422 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject y42/clj-druid "0.2.11" +(defproject y42/clj-druid "0.2.12" :description "Clojure library for Druid.io" :url "http://github.com/y42/clj-druid" :license {:name "Eclipse Public License" diff --git a/src/clj_druid/schemas/aggregation.clj b/src/clj_druid/schemas/aggregation.clj index 170bb80..6505b4e 100644 --- a/src/clj_druid/schemas/aggregation.clj +++ b/src/clj_druid/schemas/aggregation.clj @@ -54,20 +54,15 @@ :name s/Str :fieldName s/Str}) +(declare aggregation) + (s/defschema filteredAggregator "A filtered aggregator wraps any given aggregator, but only aggregates the values for which the given dimension filter matches. This makes it possible to compute the results of a filtered and an unfiltered aggregation simultaneously, without having to issue multiple queries, and use both results as part of post-aggregations." {:type (s/enum :filtered) :filter Filter - :aggregator (s/conditional - #(= :count (:type %)) countAggregator - #(= :longSum (:type %)) longSumAggregator - #(= :doubleSum (:type %)) doubleSumAggregator - #(= :min (:type %)) minAggregator - #(= :max (:type %)) maxAggregator - #(= :javascript (:type %)) javascriptAggregator - #(= :cardinality (:type %)) cardinalityAggregator - #(= :hyperUnique (:type %)) hyperUniqueAggregator)}) + (s/optional-key :name) s/Str + :aggregator (s/recursive #'aggregation)}) (s/defschema aggregation "Aggregations are specifications of processing over metrics available in Druid" diff --git a/src/clj_druid/schemas/filter.clj b/src/clj_druid/schemas/filter.clj index 71a9d9f..5ae604b 100644 --- a/src/clj_druid/schemas/filter.clj +++ b/src/clj_druid/schemas/filter.clj @@ -45,6 +45,8 @@ Selector filters can be used as the base filters for more complex Boolean expres #(= :regex (:type %)) regexFilter #(= :javascript (:type %)) javascriptFilter #(= :spatial (:type %)) spatialFilter + #(= :not (:type %)) {:type (s/enum :not) + :field (s/recursive #'Filter)} #(or (= :or (:type %)) (= :and (:type %))) {:type (s/enum :or :and) :fields [(s/recursive #'Filter)]})) diff --git a/test/clj_druid/validations_test.clj b/test/clj_druid/validations_test.clj index 95c6de6..a05cce4 100644 --- a/test/clj_druid/validations_test.clj +++ b/test/clj_druid/validations_test.clj @@ -104,13 +104,34 @@ :maxCoords [3 4]}} :pagingSpec {:pagingIdentifiers {} :threshold 5}}) - (def valid-topN-query (into valid-timeseries-query {:queryType :topN :dimension "dim1" :threshold 5 :metric "count"})) +(def valid-filtered-aggregation + {:queryType :timeseries + :dataSource "dev.supercell" + :granularity :all + :intervals ["2016-03-17T07:30:10.476/2016-03-17T08:30:10.476"] + :filter {:type :selector + :dimension "project_id" + :value "vgteam-TV_Shows"} + :aggregations [{:type :filtered + :filter {:type :selector + :dimension "img-adult" + :value "false"} + :aggregator {:type :filtered + :aggregator {:type :longSum + :name "qualityRows" + :fieldName "count" } + :filter {:type :not + :field {:type :selector + :dimension "quality" + :value nil}} + :name "img-adult->false->qualityRows"}}]}) + (deftest test-valid-groupby-query (is (= (validate-groupby valid-groupby-query) valid-groupby-query))) @@ -131,6 +152,10 @@ (is (= (validate-timeseries valid-timeseries-query) valid-timeseries-query))) +(deftest test-valid-filtered-aggregation + (is (= (validate-timeseries valid-filtered-aggregation) + valid-filtered-aggregation))) + (deftest test-valid-topN-query (is (= (validate-topN valid-topN-query) valid-topN-query)))