Skip to content

Commit e149db0

Browse files
authored
[ES|QL] Support avg on aggregate metric double (#130421)
Other major aggregations (min, max, sum, count) are available but avg was not. This commit adds it in.
1 parent 5d0c5e0 commit e149db0

File tree

7 files changed

+57
-12
lines changed

7 files changed

+57
-12
lines changed

docs/changelog/130421.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 130421
2+
summary: Support avg on aggregate metric double
3+
area: ES|QL
4+
type: bug
5+
issues: []

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1220,7 +1220,12 @@ public enum Cap {
12201220
/**
12211221
* FUSE command
12221222
*/
1223-
FUSE(Build.current().isSnapshot());
1223+
FUSE(Build.current().isSnapshot()),
1224+
1225+
/**
1226+
* Support avg with aggregate metric doubles
1227+
*/
1228+
AGGREGATE_METRIC_DOUBLE_AVG(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG);
12241229

12251230
private final boolean enabled;
12261231

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Avg.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import static java.util.Collections.emptyList;
2929
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.ParamOrdinal.DEFAULT;
3030
import static org.elasticsearch.xpack.esql.core.expression.TypeResolutions.isType;
31+
import static org.elasticsearch.xpack.esql.core.type.DataType.AGGREGATE_METRIC_DOUBLE;
3132

3233
public class Avg extends AggregateFunction implements SurrogateExpression {
3334
public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Avg", Avg::new);
@@ -50,7 +51,7 @@ public Avg(
5051
Source source,
5152
@Param(
5253
name = "number",
53-
type = { "double", "integer", "long" },
54+
type = { "aggregate_metric_double", "double", "integer", "long" },
5455
description = "Expression that outputs values to average."
5556
) Expression field
5657
) {
@@ -65,10 +66,10 @@ public Avg(Source source, Expression field, Expression filter) {
6566
protected Expression.TypeResolution resolveType() {
6667
return isType(
6768
field(),
68-
dt -> dt.isNumeric() && dt != DataType.UNSIGNED_LONG,
69+
dt -> dt.isNumeric() && dt != DataType.UNSIGNED_LONG || dt == AGGREGATE_METRIC_DOUBLE,
6970
sourceText(),
7071
DEFAULT,
71-
"numeric except unsigned_long or counter types"
72+
"aggregate_metric_double or numeric except unsigned_long or counter types"
7273
);
7374
}
7475

@@ -105,9 +106,12 @@ public Avg withFilter(Expression filter) {
105106
public Expression surrogate() {
106107
var s = source();
107108
var field = field();
108-
109-
return field().foldable()
110-
? new MvAvg(s, field)
111-
: new Div(s, new Sum(s, field, filter()), new Count(s, field, filter()), dataType());
109+
if (field.foldable()) {
110+
return new MvAvg(s, field);
111+
}
112+
if (field.dataType() == AGGREGATE_METRIC_DOUBLE) {
113+
return new Div(s, new Sum(s, field, filter()).surrogate(), new Count(s, field, filter()).surrogate());
114+
}
115+
return new Div(s, new Sum(s, field, filter()), new Count(s, field, filter()), dataType());
112116
}
113117
}

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,7 +2006,7 @@ public void testUnsupportedTypesInStats() {
20062006
| stats avg(x), count_distinct(x), max(x), median(x), median_absolute_deviation(x), min(x), percentile(x, 10), sum(x)
20072007
""", """
20082008
Found 8 problems
2009-
line 2:12: argument of [avg(x)] must be [numeric except unsigned_long or counter types],\
2009+
line 2:12: argument of [avg(x)] must be [aggregate_metric_double or numeric except unsigned_long or counter types],\
20102010
found value [x] type [unsigned_long]
20112011
line 2:20: argument of [count_distinct(x)] must be [any exact type except unsigned_long, _source, or counter types],\
20122012
found value [x] type [unsigned_long]
@@ -2028,7 +2028,7 @@ public void testUnsupportedTypesInStats() {
20282028
| stats avg(x), median(x), median_absolute_deviation(x), percentile(x, 10), sum(x)
20292029
""", """
20302030
Found 5 problems
2031-
line 2:10: argument of [avg(x)] must be [numeric except unsigned_long or counter types],\
2031+
line 2:10: argument of [avg(x)] must be [aggregate_metric_double or numeric except unsigned_long or counter types],\
20322032
found value [x] type [version]
20332033
line 2:18: argument of [median(x)] must be [numeric except unsigned_long or counter types],\
20342034
found value [x] type [version]

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ public void testAggsExpressionsInStatsAggs() {
359359
error("from test | stats max(max(salary)) by first_name")
360360
);
361361
assertEquals(
362-
"1:25: argument of [avg(first_name)] must be [numeric except unsigned_long or counter types],"
362+
"1:25: argument of [avg(first_name)] must be [aggregate_metric_double or numeric except unsigned_long or counter types],"
363363
+ " found value [first_name] type [keyword]",
364364
error("from test | stats count(avg(first_name)) by first_name")
365365
);

x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/AvgErrorTests.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ protected Expression build(Source source, List<Expression> args) {
3232

3333
@Override
3434
protected Matcher<String> expectedTypeErrorMatcher(List<Set<DataType>> validPerPosition, List<DataType> signature) {
35-
return equalTo(typeErrorMessage(false, validPerPosition, signature, (v, p) -> "numeric except unsigned_long or counter types"));
35+
return equalTo(
36+
typeErrorMessage(
37+
false,
38+
validPerPosition,
39+
signature,
40+
(v, p) -> "aggregate_metric_double or numeric except unsigned_long or counter types"
41+
)
42+
);
3643
}
3744
}

x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/40_tsdb.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,3 +707,27 @@ to_aggregate_metric_double with multi_values:
707707
- match: {values.0.1: '{"min":102.44400024414062,"max":195.10000610351562,"sum":297.54400634765625,"value_count":2}'}
708708
- match: {values.0.2: '{"min":64.0,"max":1456.0,"sum":2139.0,"value_count":4}'}
709709
- match: {values.0.3: '{"min":123.0,"max":1.9418924E7,"sum":1.9433032E7,"value_count":3}'}
710+
711+
---
712+
avg of aggregate_metric_double:
713+
- requires:
714+
test_runner_features: [capabilities]
715+
capabilities:
716+
- method: POST
717+
path: /_query
718+
parameters: []
719+
capabilities: [aggregate_metric_double_avg]
720+
reason: "support avg aggregations with aggregate metric double"
721+
722+
- do:
723+
allowed_warnings_regex:
724+
- "No limit defined, adding default limit of \\[.*\\]"
725+
esql.query:
726+
body:
727+
query: 'FROM test2 | STATS avg = avg(agg_metric) | KEEP avg'
728+
729+
- length: {values: 1}
730+
- length: {values.0: 1}
731+
- match: {columns.0.name: "avg"}
732+
- match: {columns.0.type: "double"}
733+
- match: {values.0.0: 4.904761904761905}

0 commit comments

Comments
 (0)