grafana/public/app/plugins/datasource/elasticsearch/query_builder.js

260 lines
6.5 KiB
JavaScript
Raw Normal View History

define([
'./query_def'
],
function (queryDef) {
'use strict';
function ElasticQueryBuilder(options) {
this.timeField = options.timeField;
this.esVersion = options.esVersion;
}
ElasticQueryBuilder.prototype.getRangeFilter = function() {
var filter = {};
filter[this.timeField] = {
gte: "$timeFrom",
lte: "$timeTo",
format: "epoch_millis",
};
return filter;
};
2015-09-06 07:45:12 -05:00
ElasticQueryBuilder.prototype.buildTermsAgg = function(aggDef, queryNode, target) {
var metricRef, metric, y;
2015-09-06 07:45:12 -05:00
queryNode.terms = { "field": aggDef.field };
if (!aggDef.settings) {
return queryNode;
}
queryNode.terms.size = parseInt(aggDef.settings.size, 10) === 0 ? 500 : parseInt(aggDef.settings.size, 10);
if (aggDef.settings.orderBy !== void 0) {
2015-09-06 07:45:12 -05:00
queryNode.terms.order = {};
queryNode.terms.order[aggDef.settings.orderBy] = aggDef.settings.order;
2015-09-06 07:45:12 -05:00
// if metric ref, look it up and add it to this agg level
metricRef = parseInt(aggDef.settings.orderBy, 10);
2015-09-06 07:45:12 -05:00
if (!isNaN(metricRef)) {
for (y = 0; y < target.metrics.length; y++) {
metric = target.metrics[y];
if (metric.id === aggDef.settings.orderBy) {
2015-09-06 07:45:12 -05:00
queryNode.aggs = {};
queryNode.aggs[metric.id] = {};
queryNode.aggs[metric.id][metric.type] = {field: metric.field};
break;
}
}
}
}
if (aggDef.settings.missing) {
queryNode.terms.missing = aggDef.settings.missing;
}
2015-09-06 07:45:12 -05:00
return queryNode;
};
ElasticQueryBuilder.prototype.getDateHistogramAgg = function(aggDef) {
var esAgg = {};
var settings = aggDef.settings || {};
esAgg.interval = settings.interval;
esAgg.field = this.timeField;
esAgg.min_doc_count = settings.min_doc_count || 0;
esAgg.extended_bounds = {min: "$timeFrom", max: "$timeTo"};
esAgg.format = "epoch_millis";
if (esAgg.interval === 'auto') {
2017-01-11 03:18:21 -06:00
esAgg.interval = "$__interval";
}
if (settings.missing) {
esAgg.missing = settings.missing;
}
return esAgg;
};
ElasticQueryBuilder.prototype.getFiltersAgg = function(aggDef) {
var filterObj = {};
for (var i = 0; i < aggDef.settings.filters.length; i++) {
var query = aggDef.settings.filters[i].query;
filterObj[query] = {
query_string: {
query: query,
analyze_wildcard: true
}
};
}
return filterObj;
};
ElasticQueryBuilder.prototype.documentQuery = function(query) {
query.size = 500;
query.sort = {};
query.sort[this.timeField] = {order: 'desc', unmapped_type: 'boolean'};
2016-11-08 15:18:59 -06:00
// fields field not supported on ES 5.x
if (this.esVersion < 5) {
query.fields = ["*", "_source"];
}
query.script_fields = {},
query.fielddata_fields = [this.timeField];
return query;
};
ElasticQueryBuilder.prototype.addAdhocFilters = function(query, adhocFilters) {
if (!adhocFilters) {
return;
}
var i, filter, condition;
for (i = 0; i < adhocFilters.length; i++) {
filter = adhocFilters[i];
condition = {};
condition[filter.key] = filter.value;
query.query.bool.filter.push({"term": condition});
}
};
ElasticQueryBuilder.prototype.build = function(target, adhocFilters, queryString) {
// make sure query has defaults;
target.metrics = target.metrics || [{ type: 'count', id: '1' }];
target.dsType = 'elasticsearch';
target.bucketAggs = target.bucketAggs || [{type: 'date_histogram', id: '2', settings: {interval: 'auto'}}];
target.timeField = this.timeField;
var i, nestedAggs, metric;
var query = {
"size": 0,
"query": {
"bool": {
"filter": [
{"range": this.getRangeFilter()},
{
"query_string": {
"analyze_wildcard": true,
"query": queryString,
2016-05-10 12:38:22 -05:00
}
}
]
}
}
};
this.addAdhocFilters(query, adhocFilters);
// handle document query
if (target.bucketAggs.length === 0) {
metric = target.metrics[0];
if (metric && metric.type !== 'raw_document') {
throw {message: 'Invalid query'};
}
return this.documentQuery(query, target);
}
nestedAggs = query;
for (i = 0; i < target.bucketAggs.length; i++) {
var aggDef = target.bucketAggs[i];
var esAgg = {};
switch(aggDef.type) {
case 'date_histogram': {
esAgg["date_histogram"] = this.getDateHistogramAgg(aggDef);
break;
}
case 'filters': {
esAgg["filters"] = {filters: this.getFiltersAgg(aggDef)};
break;
}
case 'terms': {
2015-09-06 07:45:12 -05:00
this.buildTermsAgg(aggDef, esAgg, target);
break;
}
case 'geohash_grid': {
esAgg['geohash_grid'] = {field: aggDef.field, precision: aggDef.settings.precision};
break;
}
}
nestedAggs.aggs = nestedAggs.aggs || {};
nestedAggs.aggs[aggDef.id] = esAgg;
nestedAggs = esAgg;
}
nestedAggs.aggs = {};
for (i = 0; i < target.metrics.length; i++) {
metric = target.metrics[i];
if (metric.type === 'count') {
continue;
}
2015-12-08 05:07:56 -06:00
var aggField = {};
var metricAgg = null;
if (queryDef.isPipelineAgg(metric.type)) {
if (metric.pipelineAgg && /^\d*$/.test(metric.pipelineAgg)) {
metricAgg = { buckets_path: metric.pipelineAgg };
2015-12-09 07:21:48 -06:00
} else {
continue;
}
2015-12-08 05:07:56 -06:00
} else {
metricAgg = {field: metric.field};
}
for (var prop in metric.settings) {
if (metric.settings.hasOwnProperty(prop) && metric.settings[prop] !== null) {
metricAgg[prop] = metric.settings[prop];
}
}
2015-12-08 05:07:56 -06:00
aggField[metric.type] = metricAgg;
nestedAggs.aggs[metric.id] = aggField;
}
return query;
};
ElasticQueryBuilder.prototype.getTermsQuery = function(queryDef) {
var query = {
"size": 0,
"query": {
"bool": {
"filter": [{"range": this.getRangeFilter()}]
2016-05-10 12:38:22 -05:00
}
2016-10-27 11:59:24 -05:00
}
};
if (queryDef.query) {
query.query.bool.filter.push({
"query_string": {
"analyze_wildcard": true,
"query": queryDef.query,
}
});
2016-05-10 12:38:22 -05:00
}
query.aggs = {
"1": {
"terms": {
"field": queryDef.field,
"size": 500,
"order": {
"_term": "asc"
}
},
}
};
return query;
};
return ElasticQueryBuilder;
});