diff --git a/public/app/plugins/datasource/elasticsearch/bucketAgg.js b/public/app/plugins/datasource/elasticsearch/bucketAgg.js index 32021f0ba42..33efa4cbf6a 100644 --- a/public/app/plugins/datasource/elasticsearch/bucketAgg.js +++ b/public/app/plugins/datasource/elasticsearch/bucketAgg.js @@ -39,7 +39,7 @@ function (angular, _, queryDef) { case 'date_histogram': case 'terms': { delete $scope.agg.query; - $scope.agg.type = 'select field'; + $scope.agg.field = 'select field'; break; } case 'filters': { @@ -120,6 +120,14 @@ function (angular, _, queryDef) { $scope.orderByOptions = queryDef.getOrderByOptions($scope.target); }; + $scope.getFieldsInternal = function() { + if ($scope.agg.type === 'date_histogram') { + return $scope.getFields({$fieldType: 'date'}); + } else { + return $scope.getFields(); + } + }; + $scope.addBucketAgg = function() { // if last is date histogram add it before var lastBucket = bucketAggs[bucketAggs.length - 1]; @@ -133,7 +141,7 @@ function (angular, _, queryDef) { return parseInt(val.id) > max ? parseInt(val.id) : max; }, 0); - bucketAggs.splice(addIndex, 0, {type: "terms", field: "select field", id: (id+1).toString()}); + bucketAggs.splice(addIndex, 0, {type: "terms", field: "select field", id: (id+1).toString(), fake: true}); $scope.onChange(); }; diff --git a/public/app/plugins/datasource/elasticsearch/datasource.js b/public/app/plugins/datasource/elasticsearch/datasource.js index 564ffff5230..b8491309881 100644 --- a/public/app/plugins/datasource/elasticsearch/datasource.js +++ b/public/app/plugins/datasource/elasticsearch/datasource.js @@ -14,7 +14,7 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes var module = angular.module('grafana.services'); - module.factory('ElasticDatasource', function($q, backendSrv, templateSrv) { + module.factory('ElasticDatasource', function($q, backendSrv, templateSrv, timeSrv) { function ElasticDatasource(datasource) { this.type = 'elasticsearch'; @@ -168,7 +168,6 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes payload = payload.replace(/\$interval/g, options.interval); payload = payload.replace(/\$timeFrom/g, options.range.from.valueOf()); payload = payload.replace(/\$timeTo/g, options.range.to.valueOf()); - payload = payload.replace(/\$maxDataPoints/g, options.maxDataPoints); payload = templateSrv.replace(payload, options.scopedVars); return this._post('/_msearch?search_type=count', payload).then(function(res) { @@ -176,9 +175,17 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes }); }; - ElasticDatasource.prototype.metricFindQuery = function() { + ElasticDatasource.prototype.getFields = function(query) { return this._get('/_mapping').then(function(res) { var fields = {}; + var typeMap = { + 'float': 'number', + 'double': 'number', + 'integer': 'number', + 'long': 'number', + 'date': 'date', + 'string': 'string', + }; for (var indexName in res) { var index = res[indexName]; @@ -188,21 +195,53 @@ function (angular, _, moment, kbn, ElasticQueryBuilder, IndexPattern, ElasticRes var properties = mappings[typeName].properties; for (var field in properties) { var prop = properties[field]; + if (query.type && typeMap[prop.type] !== query.type) { + continue; + } if (prop.type && field[0] !== '_') { - fields[field] = prop; + fields[field] = {text: field, type: prop.type}; } } } } - fields = _.map(_.keys(fields), function(field) { - return {text: field}; + // transform to array + return _.map(fields, function(value) { + return value; }); - - return fields; }); }; + ElasticDatasource.prototype.getTerms = function(queryDef) { + var range = timeSrv.timeRange(); + var header = this.getQueryHeader(range.from, range.to); + var esQuery = angular.toJson(this.queryBuilder.getTermsQuery(queryDef)); + + esQuery = esQuery.replace("$lucene_query", queryDef.query || '*'); + esQuery = esQuery.replace(/\$timeFrom/g, range.from.valueOf()); + esQuery = esQuery.replace(/\$timeTo/g, range.to.valueOf()); + esQuery = header + '\n' + esQuery + '\n'; + + return this._post('/_msearch?search_type=count', esQuery).then(function(res) { + var buckets = res.responses[0].aggregations["1"].buckets; + return _.map(buckets, function(bucket) { + return {text: bucket.key, value: bucket.key}; + }); + }); + }; + + ElasticDatasource.prototype.metricFindQuery = function(query) { + query = templateSrv.replace(query); + query = angular.fromJson(query); + + if (query.find === 'fields') { + return this.getFields(query); + } + if (query.find === 'terms') { + return this.getTerms(query); + } + }; + ElasticDatasource.prototype.getDashboard = function(id) { return this._get('/dashboard/' + id) .then(function(result) { diff --git a/public/app/plugins/datasource/elasticsearch/metricAgg.js b/public/app/plugins/datasource/elasticsearch/metricAgg.js index 1fe393138d5..f2edd203e86 100644 --- a/public/app/plugins/datasource/elasticsearch/metricAgg.js +++ b/public/app/plugins/datasource/elasticsearch/metricAgg.js @@ -70,6 +70,10 @@ function (angular, _, queryDef) { $scope.onChange(); }; + $scope.getFieldsInternal = function() { + return $scope.getFields({$fieldType: 'number'}); + }; + $scope.addMetricAgg = function() { var addIndex = metricAggs.length; diff --git a/public/app/plugins/datasource/elasticsearch/partials/bucketAgg.html b/public/app/plugins/datasource/elasticsearch/partials/bucketAgg.html index b783b3c2efc..70a8a512d72 100644 --- a/public/app/plugins/datasource/elasticsearch/partials/bucketAgg.html +++ b/public/app/plugins/datasource/elasticsearch/partials/bucketAgg.html @@ -8,7 +8,7 @@
  • - +
  •   diff --git a/public/app/plugins/datasource/elasticsearch/partials/metricAgg.html b/public/app/plugins/datasource/elasticsearch/partials/metricAgg.html index e38fdb2d39b..7d58be38094 100644 --- a/public/app/plugins/datasource/elasticsearch/partials/metricAgg.html +++ b/public/app/plugins/datasource/elasticsearch/partials/metricAgg.html @@ -7,7 +7,7 @@
  • - +
  • {{settingsLinkText}} diff --git a/public/app/plugins/datasource/elasticsearch/partials/query.editor.html b/public/app/plugins/datasource/elasticsearch/partials/query.editor.html index fe3900fcbad..dee2401e6f3 100644 --- a/public/app/plugins/datasource/elasticsearch/partials/query.editor.html +++ b/public/app/plugins/datasource/elasticsearch/partials/query.editor.html @@ -65,7 +65,7 @@
    @@ -73,7 +73,7 @@
    diff --git a/public/app/plugins/datasource/elasticsearch/queryBuilder.js b/public/app/plugins/datasource/elasticsearch/queryBuilder.js index f303c93952c..6a639e2db8d 100644 --- a/public/app/plugins/datasource/elasticsearch/queryBuilder.js +++ b/public/app/plugins/datasource/elasticsearch/queryBuilder.js @@ -151,6 +151,39 @@ function (angular) { return query; }; + ElasticQueryBuilder.prototype.getTermsQuery = function(queryDef) { + var query = { + "size": 0, + "query": { + "filtered": { + "query": { + "query_string": { + "analyze_wildcard": true, + "query": '$lucene_query', + } + }, + "filter": { + "bool": { + "must": [{"range": this.getRangeFilter()}] + } + } + } + } + }; + query.aggs = { + "1": { + "terms": { + "field": queryDef.field, + "order": { + "_term": "asc" + } + }, + } + }; + + return query; + }; + return ElasticQueryBuilder; }); diff --git a/public/app/plugins/datasource/elasticsearch/queryCtrl.js b/public/app/plugins/datasource/elasticsearch/queryCtrl.js index 00a03207c08..3965286ac12 100644 --- a/public/app/plugins/datasource/elasticsearch/queryCtrl.js +++ b/public/app/plugins/datasource/elasticsearch/queryCtrl.js @@ -18,8 +18,9 @@ function (angular, _) { target.timeField = $scope.datasource.timeField; }; - $scope.getFields = function() { - return $scope.datasource.metricFindQuery('fields()') + $scope.getFields = function(type) { + var jsonStr = angular.toJson({find: 'fields', type: type}); + return $scope.datasource.metricFindQuery(jsonStr) .then($scope.transformToSegments(false)) .then(null, $scope.handleQueryError); };