add groupby to querybuilder

remove unused aggregations
This commit is contained in:
Sven Klemm 2018-01-31 15:32:32 +01:00
parent 571ecdc740
commit 4dbd83fac1
4 changed files with 110 additions and 150 deletions

View File

@ -51,6 +51,27 @@
</div>
</div>
<div class="gf-form-inline">
<div class="gf-form">
<label class="gf-form-label query-keyword width-7">
<span>GROUP BY</span>
</label>
<query-part-editor ng-repeat="part in ctrl.queryModel.groupByParts"
part="part" class="gf-form-label query-part"
handle-event="ctrl.handleGroupByPartEvent(part, $index, $event)">
</query-part-editor>
</div>
<div class="gf-form">
<metric-segment segment="ctrl.groupBySegment" get-options="ctrl.getGroupByOptions()" on-change="ctrl.groupByAction(part, $index)"></metric-segment>
</div>
<div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div>
</div>
</div>
</div>
<div class="gf-form-inline">

View File

@ -22,7 +22,7 @@ export default class PostgresQuery {
target.alias = '';
target.orderByTime = target.orderByTime || 'ASC';
// target.groupBy = target.groupBy || [{ type: 'time', params: ['$__interval'] }, { type: 'fill', params: ['null'] }];
target.groupBy = target.groupBy || [{ type: 'time', params: ['$__interval'] }, { type: 'fill', params: ['null'] }];
target.select = target.select || [[{ type: 'field', params: ['value'] }]];
this.updateProjection();
@ -92,9 +92,6 @@ export default class PostgresQuery {
if (partModel.def.category === categories.Aggregations) {
return false;
}
if (partModel.def.category === categories.Selectors) {
return false;
}
return true;
});
});

View File

@ -29,6 +29,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
tableSegment: any;
timeColumnSegment: any;
selectMenu: any;
groupBySegment: any;
/** @ngInject **/
constructor($scope, $injector, private templateSrv, private $q, private uiSegmentSrv) {
@ -59,6 +60,8 @@ export class PostgresQueryCtrl extends QueryCtrl {
this.timeColumnSegment = uiSegmentSrv.newSegment(this.target.timeColumn);
this.buildSelectMenu();
this.groupBySegment = this.uiSegmentSrv.newPlusButton();
this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope);
this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
}
@ -224,6 +227,87 @@ export class PostgresQueryCtrl extends QueryCtrl {
}
}
handleGroupByPartEvent(part, index, evt) {
switch (evt.name) {
case 'get-param-options': {
var columnQuery = "SELECT column_name FROM information_schema.columns WHERE ";
columnQuery += " table_schema = '" + this.target.schema + "'";
columnQuery += " AND table_name = '" + this.target.table + "'";
return this.datasource
.metricFindQuery(columnQuery)
.then(this.transformToSegments(true))
.catch(this.handleQueryError.bind(this));
}
case 'part-param-changed': {
this.panelCtrl.refresh();
break;
}
case 'action': {
this.queryModel.removeGroupByPart(part, index);
this.panelCtrl.refresh();
break;
}
case 'get-part-actions': {
return this.$q.when([{ text: 'Remove', value: 'remove-part' }]);
}
}
}
getGroupByOptions() {
var columnQuery = "SELECT column_name FROM information_schema.columns WHERE ";
columnQuery += " table_schema = '" + this.target.schema + "'";
columnQuery += " AND table_name = '" + this.target.table + "'";
return this.datasource
.metricFindQuery(columnQuery)
.then(tags => {
var options = [];
if (!this.queryModel.hasFill()) {
options.push(this.uiSegmentSrv.newSegment({ value: 'fill(null)' }));
}
if (!this.target.limit) {
options.push(this.uiSegmentSrv.newSegment({ value: 'LIMIT' }));
}
if (!this.target.slimit) {
options.push(this.uiSegmentSrv.newSegment({ value: 'SLIMIT' }));
}
if (this.target.orderByTime === 'ASC') {
options.push(this.uiSegmentSrv.newSegment({ value: 'ORDER BY time DESC' }));
}
if (!this.queryModel.hasGroupByTime()) {
options.push(this.uiSegmentSrv.newSegment({ value: 'time($interval)' }));
}
for (let tag of tags) {
options.push(this.uiSegmentSrv.newSegment({ value: 'tag(' + tag.text + ')' }));
}
return options;
})
.catch(this.handleQueryError.bind(this));
}
groupByAction() {
switch (this.groupBySegment.value) {
case 'LIMIT': {
this.target.limit = 10;
break;
}
case 'ORDER BY time DESC': {
this.target.orderByTime = 'DESC';
break;
}
default: {
this.queryModel.addGroupBy(this.groupBySegment.value);
}
}
var plusButton = this.uiSegmentSrv.newPlusButton();
this.groupBySegment.value = plusButton.value;
this.groupBySegment.html = plusButton.html;
this.panelCtrl.refresh();
}
handleQueryError(err) {
this.error = err.message || 'Failed to issue metric query';
return [];

View File

@ -4,9 +4,6 @@ import { QueryPartDef, QueryPart, functionRenderer, suffixRenderer } from 'app/c
var index = [];
var categories = {
Aggregations: [],
Selectors: [],
Transformations: [],
Predictors: [],
Math: [],
Aliasing: [],
Fields: [],
@ -44,10 +41,6 @@ function replaceAggregationAddStrategy(selectParts, partModel) {
selectParts[i] = partModel;
return;
}
if (part.def.category === categories.Selectors) {
selectParts[i] = partModel;
return;
}
}
selectParts.splice(1, 0, partModel);
@ -147,34 +140,10 @@ register({
// transformations
register({
type: 'derivative',
addStrategy: addTransformationStrategy,
category: categories.Transformations,
params: [
{
name: 'duration',
type: 'interval',
options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h'],
},
],
defaultParams: ['10s'],
renderer: functionRenderer,
});
register({
type: 'spread',
addStrategy: addTransformationStrategy,
category: categories.Transformations,
params: [],
defaultParams: [],
renderer: functionRenderer,
});
register({
type: 'non_negative_derivative',
addStrategy: addTransformationStrategy,
category: categories.Transformations,
category: categories.Aggregations,
params: [
{
name: 'duration',
@ -186,46 +155,10 @@ register({
renderer: functionRenderer,
});
register({
type: 'difference',
addStrategy: addTransformationStrategy,
category: categories.Transformations,
params: [],
defaultParams: [],
renderer: functionRenderer,
});
register({
type: 'non_negative_difference',
addStrategy: addTransformationStrategy,
category: categories.Transformations,
params: [],
defaultParams: [],
renderer: functionRenderer,
});
register({
type: 'moving_average',
addStrategy: addTransformationStrategy,
category: categories.Transformations,
params: [{ name: 'window', type: 'int', options: [5, 10, 20, 30, 40] }],
defaultParams: [10],
renderer: functionRenderer,
});
register({
type: 'cumulative_sum',
addStrategy: addTransformationStrategy,
category: categories.Transformations,
params: [],
defaultParams: [],
renderer: functionRenderer,
});
register({
type: 'stddev',
addStrategy: addTransformationStrategy,
category: categories.Transformations,
category: categories.Aggregations,
params: [],
defaultParams: [],
renderer: functionRenderer,
@ -259,60 +192,11 @@ register({
renderer: functionRenderer,
});
register({
type: 'elapsed',
addStrategy: addTransformationStrategy,
category: categories.Transformations,
params: [
{
name: 'duration',
type: 'interval',
options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h'],
},
],
defaultParams: ['10s'],
renderer: functionRenderer,
});
// predictions
register({
type: 'holt_winters',
addStrategy: addTransformationStrategy,
category: categories.Predictors,
params: [
{ name: 'number', type: 'int', options: [5, 10, 20, 30, 40] },
{ name: 'season', type: 'int', options: [0, 1, 2, 5, 10] },
],
defaultParams: [10, 2],
renderer: functionRenderer,
});
register({
type: 'holt_winters_with_fit',
addStrategy: addTransformationStrategy,
category: categories.Predictors,
params: [
{ name: 'number', type: 'int', options: [5, 10, 20, 30, 40] },
{ name: 'season', type: 'int', options: [0, 1, 2, 5, 10] },
],
defaultParams: [10, 2],
renderer: functionRenderer,
});
// Selectors
register({
type: 'bottom',
addStrategy: replaceAggregationAddStrategy,
category: categories.Selectors,
params: [{ name: 'count', type: 'int' }],
defaultParams: [3],
renderer: functionRenderer,
});
register({
type: 'max',
addStrategy: replaceAggregationAddStrategy,
category: categories.Selectors,
category: categories.Aggregations,
params: [],
defaultParams: [],
renderer: functionRenderer,
@ -321,38 +205,12 @@ register({
register({
type: 'min',
addStrategy: replaceAggregationAddStrategy,
category: categories.Selectors,
category: categories.Aggregations,
params: [],
defaultParams: [],
renderer: functionRenderer,
});
register({
type: 'percentile',
addStrategy: replaceAggregationAddStrategy,
category: categories.Selectors,
params: [{ name: 'nth', type: 'int' }],
defaultParams: [95],
renderer: functionRenderer,
});
register({
type: 'top',
addStrategy: replaceAggregationAddStrategy,
category: categories.Selectors,
params: [{ name: 'count', type: 'int' }],
defaultParams: [3],
renderer: functionRenderer,
});
register({
type: 'tag',
category: groupByTimeFunctions,
params: [{ name: 'tag', type: 'string', dynamicLookup: true }],
defaultParams: ['tag'],
renderer: fieldRenderer,
});
register({
type: 'math',
addStrategy: addMathStrategy,