Skip to content

Commit

Permalink
Change the implementation to use singleRercentileRank agg config
Browse files Browse the repository at this point in the history
  • Loading branch information
stratoula committed May 26, 2022
1 parent 58e7867 commit 95f0a45
Show file tree
Hide file tree
Showing 36 changed files with 445 additions and 191 deletions.
2 changes: 2 additions & 0 deletions src/plugins/data/common/search/aggs/agg_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const getAggTypes = () => ({
{ name: METRIC_TYPES.SUM, fn: metrics.getSumMetricAgg },
{ name: METRIC_TYPES.MEDIAN, fn: metrics.getMedianMetricAgg },
{ name: METRIC_TYPES.SINGLE_PERCENTILE, fn: metrics.getSinglePercentileMetricAgg },
{ name: METRIC_TYPES.SINGLE_PERCENTILE_RANK, fn: metrics.getSinglePercentileRankMetricAgg },
{ name: METRIC_TYPES.MIN, fn: metrics.getMinMetricAgg },
{ name: METRIC_TYPES.MAX, fn: metrics.getMaxMetricAgg },
{ name: METRIC_TYPES.STD_DEV, fn: metrics.getStdDeviationMetricAgg },
Expand Down Expand Up @@ -102,6 +103,7 @@ export const getAggTypesFunctions = () => [
metrics.aggMax,
metrics.aggMedian,
metrics.aggSinglePercentile,
metrics.aggSinglePercentileRank,
metrics.aggMin,
metrics.aggMovingAvg,
metrics.aggPercentileRanks,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/plugins/data/common/search/aggs/metrics/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export * from './percentile_ranks_fn';
export * from './percentile_ranks';
export * from './percentiles_fn';
export * from './percentiles';
export * from './single_percentile_rank_fn';
export * from './single_percentile_rank';
export * from './serial_diff_fn';
export * from './serial_diff';
export * from './std_deviation_fn';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export enum METRIC_TYPES {
GEO_CENTROID = 'geo_centroid',
MEDIAN = 'median',
SINGLE_PERCENTILE = 'single_percentile',
SINGLE_PERCENTILE_RANK = 'single_percentile_rank',
MIN = 'min',
MAX = 'max',
MOVING_FN = 'moving_avg',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,5 @@ export const getPercentileRanksMetricAgg = ({
getValue(agg, bucket) {
return getPercentileValue(agg, bucket) / 100;
},
getValueBucketPath(aggConfig) {
if (aggConfig.key) {
return `${aggConfig.id}`;
}
return `${aggConfig.id}.${aggConfig.params.values[0]}`;
},
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,4 @@ describe('getPercentileValue', () => {
const value = getPercentileValue(agg, bucket);
expect(value).toEqual(24.21909648206358);
});

test('should return the correct value for an TAggConfig', () => {
const agg = {
id: '0-metric',
enabled: true,
type: 'percentile_ranks',
params: {
field: 'AvgTicketPrice',
values: [400],
},
schema: 'metric',
} as unknown as IResponseAggConfig;
const bucket = {
doc_count: 290,
'0-metric': {
values: [
{
key: 400,
value: 25.84782692356769,
},
],
},
};
const value = getPercentileValue(agg, bucket);
expect(value).toEqual(25.84782692356769);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,9 @@ export const getPercentileValue = <TAggConfig extends IResponseAggConfig>(
agg: TAggConfig,
bucket: any
) => {
const { values } = bucket[agg.parentId ?? agg.id] ?? {};
const { values } = bucket[agg.parentId] ?? {};

const percentile: any = find(values, ({ key }) => {
if (agg.key) {
return key === agg.key;
}

return key === agg.params.values[0];
});
const percentile: any = find(values, ({ key }) => key === agg.key);

return percentile ? percentile.value : NaN;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { AggConfigs, IAggConfigs } from '../agg_configs';
import { mockAggTypesRegistry } from '../test_helpers';
import { METRIC_TYPES } from './metric_agg_types';

describe('AggTypeMetricSinglePercentileRankProvider class', () => {
let aggConfigs: IAggConfigs;

beforeEach(() => {
const typesRegistry = mockAggTypesRegistry();
const field = {
name: 'bytes',
};
const indexPattern = {
id: '1234',
title: 'logstash-*',
fields: {
getByName: () => field,
filter: () => [field],
},
} as any;

aggConfigs = new AggConfigs(
indexPattern,
[
{
id: METRIC_TYPES.SINGLE_PERCENTILE_RANK,
type: METRIC_TYPES.SINGLE_PERCENTILE_RANK,
schema: 'metric',
params: {
field: 'bytes',
value: 1024,
},
},
],
{
typesRegistry,
}
);
});

it('requests the percentile ranks aggregation in the Elasticsearch query DSL', () => {
const dsl: Record<string, any> = aggConfigs.toDsl();

expect(dsl.single_percentile_rank.percentile_ranks.field).toEqual('bytes');
expect(dsl.single_percentile_rank.percentile_ranks.values).toEqual([1024]);
});

it('points to right value within multi metric for value bucket path', () => {
expect(aggConfigs.byId(METRIC_TYPES.SINGLE_PERCENTILE_RANK)!.getValueBucketPath()).toEqual(
`${METRIC_TYPES.SINGLE_PERCENTILE_RANK}.1024`
);
});

it('converts the response', () => {
const agg = aggConfigs.getResponseAggs()[0];

expect(
agg.getValue({
[agg.id]: {
values: {
'1024.0': 123,
},
},
})
).toEqual(1.23);
});

it('should not throw error for empty buckets', () => {
const agg = aggConfigs.getResponseAggs()[0];
expect(agg.getValue({})).toEqual(NaN);
});

it('produces the expected expression ast', () => {
const agg = aggConfigs.getResponseAggs()[0];
expect(agg.toExpressionAst()).toMatchInlineSnapshot(`
Object {
"chain": Array [
Object {
"arguments": Object {
"enabled": Array [
true,
],
"field": Array [
"bytes",
],
"id": Array [
"single_percentile_rank",
],
"schema": Array [
"metric",
],
"value": Array [
1024,
],
},
"function": "aggSinglePercentileRank",
"type": "function",
},
],
"type": "expression",
}
`);
});

it('supports scripted fields', () => {
const typesRegistry = mockAggTypesRegistry();
const field = {
name: 'bytes',
scripted: true,
language: 'painless',
script: 'return 456',
};
const indexPattern = {
id: '1234',
title: 'logstash-*',
fields: {
getByName: () => field,
filter: () => [field],
},
} as any;

aggConfigs = new AggConfigs(
indexPattern,
[
{
id: METRIC_TYPES.SINGLE_PERCENTILE_RANK,
type: METRIC_TYPES.SINGLE_PERCENTILE_RANK,
schema: 'metric',
params: {
field: 'bytes',
value: 1024,
},
},
],
{
typesRegistry,
}
);

expect(aggConfigs.toDsl()).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { i18n } from '@kbn/i18n';
import { aggSinglePercentileRankFnName } from './single_percentile_rank_fn';
import { MetricAggType } from './metric_agg_type';
import { METRIC_TYPES } from './metric_agg_types';
import type { IResponseAggConfig } from './lib/get_response_agg_config_class';
import { KBN_FIELD_TYPES } from '../../..';
import { BaseAggParams } from '../types';

const singlePercentileTitle = i18n.translate('data.search.aggs.metrics.singlePercentileRankTitle', {
defaultMessage: 'Percentile rank',
});

export interface AggParamsSinglePercentileRank extends BaseAggParams {
field: string;
value: number;
}

export const getSinglePercentileRankMetricAgg = () => {
return new MetricAggType<IResponseAggConfig>({
name: METRIC_TYPES.SINGLE_PERCENTILE_RANK,
expressionName: aggSinglePercentileRankFnName,
dslName: 'percentile_ranks',
title: singlePercentileTitle,
valueType: 'number',
makeLabel(aggConfig) {
return i18n.translate('data.search.aggs.metrics.singlePercentileRankLabel', {
defaultMessage: 'Percentile rank of {field}',
values: { field: aggConfig.getFieldDisplayName() },
});
},
getValueBucketPath(aggConfig) {
return `${aggConfig.id}.${aggConfig.params.value}`;
},
getSerializedFormat(agg) {
return {
id: 'percent',
};
},
params: [
{
name: 'field',
type: 'field',
filterFieldTypes: [KBN_FIELD_TYPES.NUMBER, KBN_FIELD_TYPES.HISTOGRAM],
},
{
name: 'value',
default: 0,
write: (agg, output) => {
output.params.values = [agg.params.value];
},
},
],
getValue(agg, bucket) {
let valueKey = String(agg.params.value);
if (Number.isInteger(agg.params.value)) {
valueKey += '.0';
}
const { values } = bucket[agg.id] ?? {};
return values ? values[valueKey] / 100 : NaN;
},
});
};
Loading

0 comments on commit 95f0a45

Please sign in to comment.