From aea3cbf953b31432971f7c9382e774b5118f0f18 Mon Sep 17 00:00:00 2001 From: ppisljar Date: Mon, 6 Feb 2017 17:12:36 +0100 Subject: [PATCH] adding bucket_sum aggregation --- .../public/agg_types/controls/sub_metric.html | 14 +++ src/ui/public/agg_types/index.js | 4 +- src/ui/public/agg_types/metrics/bucket_sum.js | 18 ++++ .../lib/sibling_pipeline_agg_controller.js | 31 +++++++ .../lib/sibling_pipeline_agg_helper.js | 86 +++++++++++++++++++ .../lib/sibling_pipeline_agg_writter.js | 19 ++++ 6 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 src/ui/public/agg_types/controls/sub_metric.html create mode 100644 src/ui/public/agg_types/metrics/bucket_sum.js create mode 100644 src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_controller.js create mode 100644 src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_helper.js create mode 100644 src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_writter.js diff --git a/src/ui/public/agg_types/controls/sub_metric.html b/src/ui/public/agg_types/controls/sub_metric.html new file mode 100644 index 0000000000000..88011451676be --- /dev/null +++ b/src/ui/public/agg_types/controls/sub_metric.html @@ -0,0 +1,14 @@ +
+
+ +
+ + + + +
+
+ +
diff --git a/src/ui/public/agg_types/index.js b/src/ui/public/agg_types/index.js index 5f735860e0cf7..15d68fe4370b5 100644 --- a/src/ui/public/agg_types/index.js +++ b/src/ui/public/agg_types/index.js @@ -24,6 +24,7 @@ import AggTypesBucketsTermsProvider from 'ui/agg_types/buckets/terms'; import AggTypesBucketsFiltersProvider from 'ui/agg_types/buckets/filters'; import AggTypesBucketsSignificantTermsProvider from 'ui/agg_types/buckets/significant_terms'; import AggTypesBucketsGeoHashProvider from 'ui/agg_types/buckets/geo_hash'; +import AggTypesMetricsBucketSumProvider from 'ui/agg_types/metrics/bucket_sum'; export default function AggTypeService(Private) { const aggs = { @@ -42,7 +43,8 @@ export default function AggTypeService(Private) { Private(AggTypesMetricsDerivativeProvider), Private(AggTypesMetricsCumulativeSumProvider), Private(AggTypesMetricsMovingAvgProvider), - Private(AggTypesMetricsSerialDiffProvider) + Private(AggTypesMetricsSerialDiffProvider), + Private(AggTypesMetricsBucketSumProvider), ], buckets: [ Private(AggTypesBucketsDateHistogramProvider), diff --git a/src/ui/public/agg_types/metrics/bucket_sum.js b/src/ui/public/agg_types/metrics/bucket_sum.js new file mode 100644 index 0000000000000..ea067e82e46b6 --- /dev/null +++ b/src/ui/public/agg_types/metrics/bucket_sum.js @@ -0,0 +1,18 @@ +import AggTypesMetricsMetricAggTypeProvider from 'ui/agg_types/metrics/metric_agg_type'; +import { makeNestedLabel } from './lib/make_nested_label'; +import SiblingPipelineAggHelperProvider from './lib/sibling_pipeline_agg_helper'; + + +export default function AggTypeMetricDerivativeProvider(Private) { + const MetricAggType = Private(AggTypesMetricsMetricAggTypeProvider); + const siblingPipelineHelper = Private(SiblingPipelineAggHelperProvider); + + return new MetricAggType({ + name: 'sum_bucket', + title: 'Bucket Sum', + makeLabel: agg => makeNestedLabel(agg, 'overall sum'), + params: [ + ...siblingPipelineHelper.params() + ] + }); +} diff --git a/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_controller.js b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_controller.js new file mode 100644 index 0000000000000..4d08761826e0c --- /dev/null +++ b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_controller.js @@ -0,0 +1,31 @@ +import safeMakeLabel from './safe_make_label'; + +const siblingPipelineAggController = function (type) { + return function ($scope) { + + $scope.aggType = type; + //$scope.aggParam = $scope.agg.params[type]; + $scope.aggTitle = type === 'customMetric' ? 'Metric' : 'Bucket'; + $scope.aggGroup = type === 'customMetric' ? 'metrics' : 'buckets'; + $scope.safeMakeLabel = safeMakeLabel; + + $scope.rejectAgg = function (agg) { + const invalidAggs = ['top_hits', 'percentiles', 'percentile_ranks', 'median', 'std_dev']; + return Boolean(invalidAggs.find(agg.type.name)); + }; + + //$scope.$watch(`agg.params.${type}`, updateAgg); + + function updateAgg() { + const agg = $scope.agg; + const params = agg.params; + const paramDef = agg.type.params.byName[type]; + + params[type] = params[type] || paramDef.makeAgg(agg); + } + + updateAgg(); + }; +}; + +export { siblingPipelineAggController }; diff --git a/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_helper.js b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_helper.js new file mode 100644 index 0000000000000..60b0e3d851cd1 --- /dev/null +++ b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_helper.js @@ -0,0 +1,86 @@ +import _ from 'lodash'; +import VisAggConfigProvider from 'ui/vis/agg_config'; +import VisSchemasProvider from 'ui/vis/schemas'; + +import { siblingPipelineAggController } from './sibling_pipeline_agg_controller'; +import { siblingPipelineAggWritter } from './sibling_pipeline_agg_writter'; +import metricAggTemplate from 'ui/agg_types/controls/sub_metric.html'; + +const SiblingPipelineAggHelperProvider = function (Private) { + + const AggConfig = Private(VisAggConfigProvider); + const Schemas = Private(VisSchemasProvider); + + const metricAggFilter = ['!top_hits', '!percentiles', '!percentile_ranks', '!median', '!std_dev']; + const metricAggSchema = (new Schemas([ + { + group: 'none', + name: 'metricAgg', + title: 'Metric Agg', + aggFilter: metricAggFilter + } + ])).all[0]; + + const bucketAggFilter = []; + const bucketAggSchema = (new Schemas([ + { + group: 'none', + title: 'Bucket Agg', + name: 'bucketAgg', + aggFilter: bucketAggFilter + } + ])).all[0]; + + return { + params: function () { + return [ + { + name: 'customBucket', + type: AggConfig, + default: null, + serialize: function (customMetric) { + return customMetric.toJSON(); + }, + deserialize: function (state, agg) { + return this.makeAgg(agg, state); + }, + makeAgg: function (agg, state) { + state = state || {}; + state.schema = bucketAggSchema; + const orderAgg = new AggConfig(agg.vis, state); + orderAgg.id = agg.id + '-bucket'; + return orderAgg; + }, + editor: metricAggTemplate, + controller: siblingPipelineAggController('customBucket'), + write: _.noop + }, + { + name: 'customMetric', + type: AggConfig, + default: null, + serialize: function (customMetric) { + return customMetric.toJSON(); + }, + deserialize: function (state, agg) { + return this.makeAgg(agg, state); + }, + makeAgg: function (agg, state) { + state = state || {}; + state.schema = metricAggSchema; + const orderAgg = new AggConfig(agg.vis, state); + orderAgg.id = agg.id + '-metric'; + return orderAgg; + }, + editor: metricAggTemplate, + controller: siblingPipelineAggController('customMetric'), + write: siblingPipelineAggWritter + } + ]; + } + }; + + +}; + +export default SiblingPipelineAggHelperProvider; diff --git a/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_writter.js b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_writter.js new file mode 100644 index 0000000000000..2b7b51f64d059 --- /dev/null +++ b/src/ui/public/agg_types/metrics/lib/sibling_pipeline_agg_writter.js @@ -0,0 +1,19 @@ +const siblingPipelineAggWritter = function (agg, output) { + if (!agg.params.customMetric) return; + + const metricAgg = agg.params.customMetric; + const bucketAgg = agg.params.customBucket; + + // if a bucket is selected, we must add this agg as a sibling to it, and add a metric to that bucket (or select one of its) + if (metricAgg.type.name !== 'count') { + bucketAgg.subAggs = (output.subAggs || []).concat(metricAgg); + output.params.buckets_path = `${bucketAgg.id}>${metricAgg.id}`; + } else { + output.params.buckets_path = bucketAgg.id + '>_count'; + } + + output.parentAggs = (output.parentAggs || []).concat(bucketAgg); + +}; + +export { siblingPipelineAggWritter };