diff --git a/public/app/plugins/datasource/elasticsearch/bucket_agg.js b/public/app/plugins/datasource/elasticsearch/bucket_agg.js
index 28f1df08251..7b3685fca5a 100644
--- a/public/app/plugins/datasource/elasticsearch/bucket_agg.js
+++ b/public/app/plugins/datasource/elasticsearch/bucket_agg.js
@@ -17,6 +17,7 @@ function (angular, _, queryDef) {
target: "=",
index: "=",
onChange: "&",
+ // getNestedKeys: "&",
getFields: "&",
}
};
@@ -52,14 +53,25 @@ function (angular, _, queryDef) {
case 'date_histogram':
case 'terms': {
delete $scope.agg.query;
+ delete $scope.agg.settings.nested.path;
$scope.agg.field = 'select field';
break;
}
case 'filters': {
delete $scope.agg.field;
+ delete $scope.agg.settings.nested.path;
$scope.agg.query = '*';
break;
}
+ case 'nested': {
+ delete $scope.agg.field;
+ delete $scope.agg.query;
+ $scope.agg.settings.nested = {};
+ $scope.agg.settings.nested.path = 'select field (type: nested)';
+ $scope.agg.settings.nested.term = 'select nested term path';
+ $scope.agg.settings.nested.query = 'select query for Nested Term';
+ break;
+ }
case 'geohash_grid': {
$scope.agg.settings.precision = 3;
break;
@@ -79,6 +91,12 @@ function (angular, _, queryDef) {
var settings = $scope.agg.settings || {};
switch($scope.agg.type) {
+ case 'nested': {
+ if (settingsLinkText === '') {
+ settingsLinkText = 'Options';
+ }
+ break;
+ }
case 'terms': {
settings.order = settings.order || "asc";
settings.size = settings.size || "10";
@@ -170,6 +188,20 @@ function (angular, _, queryDef) {
}
};
+ $scope.getFieldsNestedPath = function() {
+ return $scope.getFields({$fieldType: 'nested'});
+ };
+
+ $scope.getFieldsNestedTerm = function() {
+ return $scope.getFields({$fieldType: 'string'});
+ };
+
+ // FIX THIS: add a method getNestedKeys to be called here
+ // for getting nested key string ids, based on term/path supplied.
+ // $scope.getFieldsNestedQuery = function() {
+ // return $scope.getNestedKeys();
+ // };
+
$scope.getIntervalOptions = function() {
return $q.when(uiSegmentSrv.transformToSegments(true, 'interval')(queryDef.intervalOptions));
};
diff --git a/public/app/plugins/datasource/elasticsearch/datasource.js b/public/app/plugins/datasource/elasticsearch/datasource.js
index 4377d634982..14601314118 100644
--- a/public/app/plugins/datasource/elasticsearch/datasource.js
+++ b/public/app/plugins/datasource/elasticsearch/datasource.js
@@ -290,9 +290,10 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes
}
// transform to array
- return _.map(fields, function(value) {
+ var resp = _.map(fields, function(value) {
return value;
});
+ return resp;
});
};
diff --git a/public/app/plugins/datasource/elasticsearch/elastic_response.js b/public/app/plugins/datasource/elasticsearch/elastic_response.js
index 27285852e33..125abc8690a 100644
--- a/public/app/plugins/datasource/elasticsearch/elastic_response.js
+++ b/public/app/plugins/datasource/elasticsearch/elastic_response.js
@@ -97,6 +97,33 @@ function (_, queryDef) {
}
};
+ ElasticResponse.prototype.processNestedAggregationDocs = function(esAgg, aggDef, target, seriesList, props) {
+ var metric, y, i, newSeries, bucket, value;
+
+ for (y = 0; y < target.metrics.length; y++) {
+ metric = target.metrics[y];
+ if (metric.hide) {
+ continue;
+ }
+
+ newSeries = { datapoints: [], metric: metric.type, field: metric.field, props: props};
+ for (i = 0; i < esAgg.buckets.length; i++) {
+ bucket = esAgg.buckets[i][aggDef.id]['nested_aggs'];
+ if (bucket !== undefined) {
+ value = bucket[metric.id];
+ if (value !== undefined) {
+ if (value.normalized_value) {
+ newSeries.datapoints.push([value.normalized_value, esAgg.buckets[i].key]);
+ } else {
+ newSeries.datapoints.push([value.value, esAgg.buckets[i].key]);
+ }
+ }
+ }
+ }
+ seriesList.push(newSeries);
+ }
+ };
+
ElasticResponse.prototype.processAggregationDocs = function(esAgg, aggDef, target, docs, props) {
var metric, y, i, bucket, metricName, doc;
@@ -145,31 +172,39 @@ function (_, queryDef) {
// This is quite complex
// neeed to recurise down the nested buckets to build series
ElasticResponse.prototype.processBuckets = function(aggs, target, seriesList, docs, props, depth) {
- var bucket, aggDef, esAgg, aggId;
+ var bucket, aggDef, aggDefNested, esAgg, aggId;
var maxDepth = target.bucketAggs.length-1;
+ aggDefNested = _.find(target.bucketAggs, {type: "nested"});
+
for (aggId in aggs) {
- aggDef = _.find(target.bucketAggs, {id: aggId});
esAgg = aggs[aggId];
- if (!aggDef) {
- continue;
- }
-
- if (depth === maxDepth) {
- if (aggDef.type === 'date_histogram') {
- this.processMetrics(esAgg, target, seriesList, props);
- } else {
- this.processAggregationDocs(esAgg, aggDef, target, docs, props);
- }
+ if (aggDefNested) {
+ this.processNestedAggregationDocs(esAgg, aggDefNested, target, seriesList, props);
} else {
- for (var nameIndex in esAgg.buckets) {
- bucket = esAgg.buckets[nameIndex];
- props = _.clone(props);
- if (bucket.key !== void 0) {
- props[aggDef.field] = bucket.key;
+ aggDef = _.find(target.bucketAggs, {id: aggId});
+
+ if (!aggDef) {
+ continue;
+ }
+
+ if (depth === maxDepth) {
+ if (aggDef.type === 'date_histogram') {
+ this.processMetrics(esAgg, target, seriesList, props);
} else {
- props["filter"] = nameIndex;
+ this.processAggregationDocs(esAgg, aggDef, target, docs, props);
+ }
+ } else {
+ for (var nameIndex in esAgg.buckets) {
+ bucket = esAgg.buckets[nameIndex];
+ props = _.clone(props);
+ if (bucket.key) {
+ props[aggDef.field] = bucket.key;
+ } else {
+ props["filter"] = nameIndex;
+ }
+ this.processBuckets(bucket, target, seriesList, docs, props, depth+1);
}
if (bucket.key_as_string) {
props[aggDef.field] = bucket.key_as_string;
@@ -293,7 +328,7 @@ function (_, queryDef) {
if (err.root_cause && err.root_cause.length > 0 && err.root_cause[0].reason) {
result.message = err.root_cause[0].reason;
} else {
- result.message = err.reason || 'Unkown elatic error response';
+ result.message = err.reason || 'Unknown elastic error response';
}
if (response.$$config) {
@@ -325,7 +360,6 @@ function (_, queryDef) {
this.processBuckets(aggregations, target, tmpSeriesList, docs, {}, 0);
this.trimDatapoints(tmpSeriesList, target);
this.nameSeries(tmpSeriesList, target);
-
for (var y = 0; y < tmpSeriesList.length; y++) {
seriesList.push(tmpSeriesList[y]);
}
diff --git a/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html b/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html
index 562f0b86e56..bc013cf519e 100644
--- a/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html
+++ b/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html
@@ -7,6 +7,7 @@