Skip to content

Commit

Permalink
Don't send index metadata, revamp Elastic querybuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
ddelemeny committed Feb 13, 2024
1 parent 873f058 commit 95ff50e
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 237 deletions.
121 changes: 52 additions & 69 deletions src/QueryBuilder/elastic.ts
Original file line number Diff line number Diff line change
@@ -1,84 +1,67 @@
import {
BucketAggregation,
ElasticsearchQuery,
MetricAggregation,
TermsQuery,
} from '../types';

export class ElasticQueryBuilder {
timeField: string;

constructor(options: { timeField: string }) {
this.timeField = options.timeField;
}

getRangeFilter() {
const filter: any = {};
filter[this.timeField] = {
gte: '$timeFrom',
lte: '$timeTo',
// FIXME when Quickwit supports format.
// format: 'epoch_millis',
};

return filter;
}

getTermsQuery(queryDef: TermsQuery) {
const query: any = {
size: 0,
query: {
bool: {
filter: [{ range: this.getRangeFilter() }],
},
},
};

if (queryDef.query) {
query.query.bool.filter.push({
query_string: {
// FIXME when Quickwit supports analyze_wildcard.
// analyze_wildcard: true,
query: queryDef.query,
},
});
}
type OrderByType = '_key' | '_term' | '_count'

let size = 500;
if (queryDef.size) {
size = queryDef.size;
function getTermsAgg(
fieldName: string,
size: number,
orderBy: OrderByType = "_key",
order: 'asc'|'desc' = 'asc'
): BucketAggregation {
return {
type: 'terms',
id: "",
field: fieldName,
settings:{
size: size.toString(),
order: order,
orderBy: orderBy,
}
}
}

query.aggs = {
'1': {
terms: {
field: queryDef.field,
size: size,
order: {},
},
},
};
export function getDataQuery(queryDef: TermsQuery, refId: string): ElasticsearchQuery {
const metrics: MetricAggregation[] = [
{id:"count1", type:'count'}
];

// Default behaviour is to order results by { _key: asc }
// queryDef.order allows selection of asc/desc
// queryDef.orderBy allows selection of doc_count ordering (defaults desc)
// Default behaviour is to order results by { _key: asc }
// queryDef.order allows selection of asc/desc
// queryDef.orderBy allows selection of doc_count ordering (defaults desc)

const { orderBy = 'key', order = orderBy === 'doc_count' ? 'desc' : 'asc' } = queryDef;
let orderBy: OrderByType;
switch (queryDef.orderBy || 'key') {
case 'key':
case 'term':
orderBy = '_key'
break;
case 'doc_count':
orderBy = '_count'
break;
default:
throw { message: `Invalid query sort type ${queryDef.orderBy}` };
}

if (['asc', 'desc'].indexOf(order) < 0) {
throw { message: `Invalid query sort order ${order}` };
}
const {order = orderBy === '_count' ? 'desc' : 'asc' } = queryDef;
if (['asc', 'desc'].indexOf(order) < 0) {
throw { message: `Invalid query sort order ${order}` };
}

switch (orderBy) {
case 'key':
case 'term':
const keyname = '_key';
query.aggs['1'].terms.order[keyname] = order;
break;
case 'doc_count':
query.aggs['1'].terms.order['_count'] = order;
break;
default:
throw { message: `Invalid query sort type ${orderBy}` };
}
const bucketAggs: BucketAggregation[] = [];
if (queryDef.field) {
bucketAggs.push(getTermsAgg(queryDef.field, 500, orderBy, order))
}

return query;
return {
refId,
metrics,
bucketAggs,
query: queryDef.query,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
} from './actions';

export const createReducer =
(defaultTimeField: string) =>
(defaultTimeField = "default timefield") =>
(state: ElasticsearchQuery['bucketAggs'], action: Action): ElasticsearchQuery['bucketAggs'] => {
if (addBucketAggregation.match(action)) {
const newAgg: Terms = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const query: ElasticsearchQuery = {

describe('ElasticsearchQueryContext', () => {
it('Should call onChange and onRunQuery with the default query when the query is empty', () => {
const datasource = { timeField: 'TIMEFIELD' } as ElasticDatasource;
const datasource = {} as ElasticDatasource;
const onChange = jest.fn();
const onRunQuery = jest.fn();

Expand All @@ -39,9 +39,6 @@ describe('ElasticsearchQueryContext', () => {
expect(changedQuery.metrics).toBeDefined();
expect(changedQuery.bucketAggs).toBeDefined();

// Should also set timeField to the configured `timeField` option in datasource configuration
expect(changedQuery.timeField).toBe(datasource.timeField);

expect(onRunQuery).toHaveBeenCalled();
});

Expand Down
5 changes: 2 additions & 3 deletions src/components/QueryEditor/ElasticsearchQueryContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,11 @@ export const ElasticsearchProvider = ({
query: queryReducer,
alias: aliasPatternReducer,
metrics: metricsReducer,
bucketAggs: createBucketAggsReducer(datasource.timeField),
bucketAggs: createBucketAggsReducer(),
});

const dispatch = useStatelessReducer(
// timeField is part of the query model, but its value is always set to be the one from datasource settings.
(newState) => onStateChange({ ...query, ...newState, timeField: datasource.timeField }),
(newState) => onStateChange({ ...query, ...newState }),
query,
reducer
);
Expand Down
2 changes: 0 additions & 2 deletions src/configuration/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import { QuickwitOptions } from 'quickwit';

export function createDefaultConfigOptions(): DataSourceSettings<QuickwitOptions> {
return createDatasourceSettings<QuickwitOptions>({
timeField: 'timestamp',
timeOutputFormat: 'unix_timestamp_millisecs',
logMessageField: 'test.message',
logLevelField: 'test.level',
index: 'test',
Expand Down
4 changes: 0 additions & 4 deletions src/dataquery.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,10 +395,6 @@ export interface Elasticsearch extends DataQuery {
* Lucene query
*/
query?: string;
/**
* Name of time field
*/
timeField?: string;
}

export const defaultElasticsearch: Partial<Elasticsearch> = {
Expand Down
Loading

0 comments on commit 95ff50e

Please sign in to comment.