Skip to content

Commit 63603ae

Browse files
'Auto' interval must be correctly calculated for natural numbers (#77995)
* 'Auto' interval must be correctly calculated for natural numbers * fix ts error * fix PR comments Co-authored-by: Elastic Machine <[email protected]>
1 parent 99bc56d commit 63603ae

File tree

3 files changed

+117
-4
lines changed

3 files changed

+117
-4
lines changed

src/plugins/data/common/search/aggs/buckets/histogram.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export const getHistogramBucketAgg = ({
158158
maxBucketsUiSettings: getConfig(UI_SETTINGS.HISTOGRAM_MAX_BARS),
159159
maxBucketsUserInput: aggConfig.params.maxBars,
160160
intervalBase: aggConfig.params.intervalBase,
161+
esTypes: aggConfig.params.field?.spec?.esTypes || [],
161162
});
162163
},
163164
},

src/plugins/data/common/search/aggs/buckets/lib/histogram_calculate_interval.test.ts

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
calculateHistogramInterval,
2222
CalculateHistogramIntervalParams,
2323
} from './histogram_calculate_interval';
24+
import { ES_FIELD_TYPES } from '../../../../types';
2425

2526
describe('calculateHistogramInterval', () => {
2627
describe('auto calculating mode', () => {
@@ -36,10 +37,91 @@ describe('calculateHistogramInterval', () => {
3637
min: 0,
3738
max: 1,
3839
},
40+
esTypes: [],
3941
};
4042
});
4143

4244
describe('maxBucketsUserInput is defined', () => {
45+
test('should set 1 as an interval for integer numbers that are less than maxBuckets #1', () => {
46+
const p = {
47+
...params,
48+
maxBucketsUserInput: 100,
49+
values: {
50+
min: 1,
51+
max: 50,
52+
},
53+
esTypes: [ES_FIELD_TYPES.INTEGER],
54+
};
55+
expect(calculateHistogramInterval(p)).toEqual(1);
56+
});
57+
58+
test('should set 1 as an interval for integer numbers that are less than maxBuckets #2', () => {
59+
const p = {
60+
...params,
61+
maxBucketsUiSettings: 1000,
62+
maxBucketsUserInput: 258,
63+
values: {
64+
min: 521,
65+
max: 689,
66+
},
67+
esTypes: [ES_FIELD_TYPES.INTEGER],
68+
};
69+
expect(calculateHistogramInterval(p)).toEqual(1);
70+
});
71+
72+
test('should set correct interval for integer numbers that are greater than maxBuckets #1', () => {
73+
const p = {
74+
...params,
75+
maxBucketsUserInput: 100,
76+
values: {
77+
min: 400,
78+
max: 790,
79+
},
80+
esTypes: [ES_FIELD_TYPES.INTEGER, ES_FIELD_TYPES.SHORT],
81+
};
82+
expect(calculateHistogramInterval(p)).toEqual(5);
83+
});
84+
85+
test('should set correct interval for integer numbers that are greater than maxBuckets #2', () => {
86+
// diff === 3456211; interval === 50000; buckets === 69
87+
const p = {
88+
...params,
89+
maxBucketsUserInput: 100,
90+
values: {
91+
min: 567,
92+
max: 3456778,
93+
},
94+
esTypes: [ES_FIELD_TYPES.LONG],
95+
};
96+
expect(calculateHistogramInterval(p)).toEqual(50000);
97+
});
98+
99+
test('should not set integer interval if the field type is float #1', () => {
100+
const p = {
101+
...params,
102+
maxBucketsUserInput: 100,
103+
values: {
104+
min: 0,
105+
max: 1,
106+
},
107+
esTypes: [ES_FIELD_TYPES.FLOAT],
108+
};
109+
expect(calculateHistogramInterval(p)).toEqual(0.01);
110+
});
111+
112+
test('should not set integer interval if the field type is float #2', () => {
113+
const p = {
114+
...params,
115+
maxBucketsUserInput: 100,
116+
values: {
117+
min: 0,
118+
max: 1,
119+
},
120+
esTypes: [ES_FIELD_TYPES.INTEGER, ES_FIELD_TYPES.FLOAT],
121+
};
122+
expect(calculateHistogramInterval(p)).toEqual(0.01);
123+
});
124+
43125
test('should not set interval which more than largest possible', () => {
44126
const p = {
45127
...params,
@@ -48,6 +130,7 @@ describe('calculateHistogramInterval', () => {
48130
min: 150,
49131
max: 250,
50132
},
133+
esTypes: [ES_FIELD_TYPES.SHORT],
51134
};
52135
expect(calculateHistogramInterval(p)).toEqual(1);
53136
});
@@ -61,6 +144,7 @@ describe('calculateHistogramInterval', () => {
61144
min: 0.1,
62145
max: 0.9,
63146
},
147+
esTypes: [ES_FIELD_TYPES.FLOAT],
64148
})
65149
).toBe(0.02);
66150
});
@@ -74,6 +158,7 @@ describe('calculateHistogramInterval', () => {
74158
min: 10.45,
75159
max: 1000.05,
76160
},
161+
esTypes: [ES_FIELD_TYPES.FLOAT],
77162
})
78163
).toBe(100);
79164
});
@@ -88,6 +173,7 @@ describe('calculateHistogramInterval', () => {
88173
min: 0,
89174
max: 100,
90175
},
176+
esTypes: [ES_FIELD_TYPES.BYTE],
91177
})
92178
).toEqual(1);
93179
});
@@ -100,8 +186,9 @@ describe('calculateHistogramInterval', () => {
100186
min: 1,
101187
max: 10,
102188
},
189+
esTypes: [ES_FIELD_TYPES.INTEGER],
103190
})
104-
).toEqual(0.1);
191+
).toEqual(1);
105192
});
106193

107194
test('should set intervals for integer numbers (diff more than maxBucketsUiSettings)', () => {
@@ -113,6 +200,7 @@ describe('calculateHistogramInterval', () => {
113200
min: 45678,
114201
max: 90123,
115202
},
203+
esTypes: [ES_FIELD_TYPES.INTEGER],
116204
})
117205
).toEqual(500);
118206
});
@@ -127,6 +215,7 @@ describe('calculateHistogramInterval', () => {
127215
min: 1.245,
128216
max: 2.9,
129217
},
218+
esTypes: [ES_FIELD_TYPES.FLOAT],
130219
})
131220
).toEqual(0.02);
132221
expect(
@@ -136,6 +225,7 @@ describe('calculateHistogramInterval', () => {
136225
min: 0.5,
137226
max: 2.3,
138227
},
228+
esTypes: [ES_FIELD_TYPES.FLOAT],
139229
})
140230
).toEqual(0.02);
141231
});
@@ -149,6 +239,7 @@ describe('calculateHistogramInterval', () => {
149239
min: 0.1,
150240
max: 0.9,
151241
},
242+
esTypes: [ES_FIELD_TYPES.FLOAT],
152243
})
153244
).toBe(0.01);
154245
});

src/plugins/data/common/search/aggs/buckets/lib/histogram_calculate_interval.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919

2020
import { isAutoInterval } from '../_interval_options';
21+
import { ES_FIELD_TYPES } from '../../../../types';
2122

2223
interface IntervalValuesRange {
2324
min: number;
@@ -28,6 +29,7 @@ export interface CalculateHistogramIntervalParams {
2829
interval: string;
2930
maxBucketsUiSettings: number;
3031
maxBucketsUserInput?: number | '';
32+
esTypes: ES_FIELD_TYPES[];
3133
intervalBase?: number;
3234
values?: IntervalValuesRange;
3335
}
@@ -77,11 +79,27 @@ const calculateForGivenInterval = (
7779
- The lower power of 10, times 2
7880
- The lower power of 10, times 5
7981
**/
80-
const calculateAutoInterval = (diff: number, maxBars: number) => {
82+
const calculateAutoInterval = (diff: number, maxBars: number, esTypes: ES_FIELD_TYPES[]) => {
8183
const exactInterval = diff / maxBars;
8284

83-
const lowerPower = Math.pow(10, Math.floor(Math.log10(exactInterval)));
85+
// For integer fields that are less than maxBars, we should use 1 as the value of interval
86+
// Elastic has 4 integer data types: long, integer, short, byte
87+
// see: https://www.elastic.co/guide/en/elasticsearch/reference/current/number.html
88+
if (
89+
diff < maxBars &&
90+
esTypes.every((esType) =>
91+
[
92+
ES_FIELD_TYPES.INTEGER,
93+
ES_FIELD_TYPES.LONG,
94+
ES_FIELD_TYPES.SHORT,
95+
ES_FIELD_TYPES.BYTE,
96+
].includes(esType)
97+
)
98+
) {
99+
return 1;
100+
}
84101

102+
const lowerPower = Math.pow(10, Math.floor(Math.log10(exactInterval)));
85103
const autoBuckets = diff / lowerPower;
86104

87105
if (autoBuckets > maxBars) {
@@ -103,6 +121,7 @@ export const calculateHistogramInterval = ({
103121
maxBucketsUserInput,
104122
intervalBase,
105123
values,
124+
esTypes,
106125
}: CalculateHistogramIntervalParams) => {
107126
const isAuto = isAutoInterval(interval);
108127
let calculatedInterval = isAuto ? 0 : parseFloat(interval);
@@ -119,8 +138,10 @@ export const calculateHistogramInterval = ({
119138
calculatedInterval = isAuto
120139
? calculateAutoInterval(
121140
diff,
141+
122142
// Mind maxBucketsUserInput can be an empty string, hence we need to ensure it here
123-
Math.min(maxBucketsUiSettings, maxBucketsUserInput || maxBucketsUiSettings)
143+
Math.min(maxBucketsUiSettings, maxBucketsUserInput || maxBucketsUiSettings),
144+
esTypes
124145
)
125146
: calculateForGivenInterval(diff, calculatedInterval, maxBucketsUiSettings);
126147
}

0 commit comments

Comments
 (0)