Skip to content

Commit 444a9db

Browse files
committed
[ES|QL] Render aggregate_metric_double
1 parent bb9c2c3 commit 444a9db

File tree

7 files changed

+91
-8
lines changed

7 files changed

+91
-8
lines changed

x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/CompositeBlock.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ public int getFirstValueIndex(int position) {
9696

9797
@Override
9898
public int getValueCount(int position) {
99-
return blocks[0].getValueCount(position);
99+
int max = 0;
100+
for (var block : blocks) {
101+
max = Math.max(max, block.getValueCount(position));
102+
}
103+
return max;
100104
}
101105

102106
@Override

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
@@ -819,7 +819,12 @@ public enum Cap {
819819
* Fixes a series of issues with inlinestats which had an incomplete implementation after lookup and inlinestats
820820
* were refactored.
821821
*/
822-
INLINESTATS_V3(EsqlPlugin.INLINESTATS_FEATURE_FLAG);
822+
INLINESTATS_V3(EsqlPlugin.INLINESTATS_FEATURE_FLAG),
823+
824+
/**
825+
* Support for rendering aggregate_metric_double type
826+
*/
827+
AGGREGATE_METRIC_DOUBLE_RENDERING(AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG);
823828

824829
private final boolean enabled;
825830

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
import org.apache.lucene.util.BytesRef;
1111
import org.elasticsearch.common.bytes.BytesArray;
1212
import org.elasticsearch.common.xcontent.XContentHelper;
13+
import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder;
1314
import org.elasticsearch.compute.data.Block;
1415
import org.elasticsearch.compute.data.BooleanBlock;
1516
import org.elasticsearch.compute.data.BytesRefBlock;
17+
import org.elasticsearch.compute.data.CompositeBlock;
1618
import org.elasticsearch.compute.data.DoubleBlock;
1719
import org.elasticsearch.compute.data.IntBlock;
1820
import org.elasticsearch.compute.data.LongBlock;
@@ -25,6 +27,7 @@
2527
import java.io.IOException;
2628

2729
import static org.elasticsearch.xpack.esql.core.util.NumericUtils.unsignedLongAsNumber;
30+
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.aggregateMetricDoubleToString;
2831
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.dateTimeToString;
2932
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.ipToString;
3033
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.nanoTimeToString;
@@ -148,8 +151,23 @@ protected XContentBuilder valueToXContent(XContentBuilder builder, ToXContent.Pa
148151
return builder.value(versionToString(val));
149152
}
150153
};
151-
// TODO: Add implementation for aggregate_metric_double
152-
case NULL, AGGREGATE_METRIC_DOUBLE -> new PositionToXContent(block) {
154+
case AGGREGATE_METRIC_DOUBLE -> new PositionToXContent(block) {
155+
@Override
156+
protected XContentBuilder valueToXContent(XContentBuilder builder, ToXContent.Params params, int valueIndex)
157+
throws IOException {
158+
CompositeBlock compositeBlock = (CompositeBlock) block;
159+
var minBlock = compositeBlock.getBlock(AggregateMetricDoubleBlockBuilder.Metric.MIN.getIndex());
160+
var maxBlock = compositeBlock.getBlock(AggregateMetricDoubleBlockBuilder.Metric.MAX.getIndex());
161+
var sumBlock = compositeBlock.getBlock(AggregateMetricDoubleBlockBuilder.Metric.SUM.getIndex());
162+
var countBlock = compositeBlock.getBlock(AggregateMetricDoubleBlockBuilder.Metric.COUNT.getIndex());
163+
Double minVal = minBlock.isNull(valueIndex) ? null : ((DoubleBlock) minBlock).getDouble(valueIndex);
164+
Double maxVal = maxBlock.isNull(valueIndex) ? null : ((DoubleBlock) maxBlock).getDouble(valueIndex);
165+
Double sumVal = sumBlock.isNull(valueIndex) ? null : ((DoubleBlock) sumBlock).getDouble(valueIndex);
166+
Integer countVal = countBlock.isNull(valueIndex) ? null : ((IntBlock) countBlock).getInt(valueIndex);
167+
return builder.value(aggregateMetricDoubleToString(maxVal, minVal, sumVal, countVal));
168+
}
169+
};
170+
case NULL -> new PositionToXContent(block) {
153171
@Override
154172
protected XContentBuilder valueToXContent(XContentBuilder builder, ToXContent.Params params, int valueIndex)
155173
throws IOException {

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
import org.elasticsearch.common.bytes.BytesArray;
1212
import org.elasticsearch.common.collect.Iterators;
1313
import org.elasticsearch.common.xcontent.XContentHelper;
14+
import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder;
1415
import org.elasticsearch.compute.data.Block;
1516
import org.elasticsearch.compute.data.BooleanBlock;
1617
import org.elasticsearch.compute.data.BytesRefBlock;
18+
import org.elasticsearch.compute.data.CompositeBlock;
1719
import org.elasticsearch.compute.data.DoubleBlock;
1820
import org.elasticsearch.compute.data.IntBlock;
1921
import org.elasticsearch.compute.data.LongBlock;
@@ -30,6 +32,7 @@
3032
import java.util.List;
3133

3234
import static org.elasticsearch.xpack.esql.core.util.NumericUtils.unsignedLongAsNumber;
35+
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.aggregateMetricDoubleToString;
3336
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.dateTimeToString;
3437
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.ipToString;
3538
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.nanoTimeToString;
@@ -132,7 +135,19 @@ private static Object valueAt(DataType dataType, Block block, int offset, BytesR
132135
case GEO_POINT, GEO_SHAPE, CARTESIAN_POINT, CARTESIAN_SHAPE -> spatialToString(
133136
((BytesRefBlock) block).getBytesRef(offset, scratch)
134137
);
135-
case UNSUPPORTED, AGGREGATE_METRIC_DOUBLE -> (String) null;
138+
case AGGREGATE_METRIC_DOUBLE -> {
139+
CompositeBlock compositeBlock = (CompositeBlock) block;
140+
var minBlock = compositeBlock.getBlock(AggregateMetricDoubleBlockBuilder.Metric.MIN.getIndex());
141+
var maxBlock = compositeBlock.getBlock(AggregateMetricDoubleBlockBuilder.Metric.MAX.getIndex());
142+
var sumBlock = compositeBlock.getBlock(AggregateMetricDoubleBlockBuilder.Metric.SUM.getIndex());
143+
var countBlock = compositeBlock.getBlock(AggregateMetricDoubleBlockBuilder.Metric.COUNT.getIndex());
144+
Double minVal = minBlock.isNull(offset) ? null : ((DoubleBlock) minBlock).getDouble(offset);
145+
Double maxVal = maxBlock.isNull(offset) ? null : ((DoubleBlock) maxBlock).getDouble(offset);
146+
Double sumVal = sumBlock.isNull(offset) ? null : ((DoubleBlock) sumBlock).getDouble(offset);
147+
Integer countVal = countBlock.isNull(offset) ? null : ((IntBlock) countBlock).getInt(offset);
148+
yield aggregateMetricDoubleToString(maxVal, minVal, sumVal, countVal);
149+
}
150+
case UNSUPPORTED -> (String) null;
136151
case SOURCE -> {
137152
BytesRef val = ((BytesRefBlock) block).getBytesRef(offset, scratch);
138153
try {

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/type/EsqlDataTypeConverter.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import java.util.List;
5959
import java.util.Locale;
6060
import java.util.Map;
61+
import java.util.StringJoiner;
6162
import java.util.function.BiFunction;
6263
import java.util.function.Function;
6364

@@ -664,6 +665,23 @@ public static long booleanToUnsignedLong(boolean number) {
664665
return number ? ONE_AS_UNSIGNED_LONG : ZERO_AS_UNSIGNED_LONG;
665666
}
666667

668+
public static String aggregateMetricDoubleToString(Double maxVal, Double minVal, Double sumVal, Integer countVal) {
669+
final StringJoiner joiner = new StringJoiner(", ");
670+
if (maxVal != null) {
671+
joiner.add("\"max\": " + maxVal);
672+
}
673+
if (minVal != null) {
674+
joiner.add("\"min\": " + minVal);
675+
}
676+
if (sumVal != null) {
677+
joiner.add("\"sum\": " + sumVal);
678+
}
679+
if (countVal != null) {
680+
joiner.add("\"value_count\": " + countVal);
681+
}
682+
return "{ " + joiner + " }";
683+
}
684+
667685
public enum EsqlConverter implements Converter {
668686

669687
STRING_TO_DATE_PERIOD(x -> EsqlDataTypeConverter.parseTemporalAmount(x, DataType.DATE_PERIOD)),

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,29 @@ stats on aggregate_metric_double missing min and max:
445445
- match: {values.0.2: 1.0}
446446
- match: {values.0.3: 10}
447447

448+
---
449+
render aggregate_metric_double when missing min and max:
450+
- requires:
451+
test_runner_features: [ capabilities ]
452+
capabilities:
453+
- method: POST
454+
path: /_query
455+
parameters: [ ]
456+
capabilities: [ aggregate_metric_double_rendering ]
457+
reason: "Support for rendering aggregate_metric_doubles"
458+
- do:
459+
allowed_warnings_regex:
460+
- "No limit defined, adding default limit of \\[.*\\]"
461+
esql.query:
462+
body:
463+
query: 'FROM test4 | KEEP agg_metric'
464+
465+
- length: {values: 1}
466+
- length: {values.0: 1}
467+
- match: {columns.0.name: "agg_metric"}
468+
- match: {columns.0.type: "aggregate_metric_double"}
469+
- match: {values.0.0: '{ "sum": 1, "value_count": 10 }'}
470+
448471
---
449472
from index pattern unsupported counter:
450473
- requires:

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ unsupported:
119119
- method: POST
120120
path: /_query
121121
parameters: [ ]
122-
capabilities: [ aggregate_metric_double ]
123-
reason: "support for aggregate_metric_double type"
122+
capabilities: [ aggregate_metric_double_rendering ]
123+
reason: "support for rendering aggregate_metric_double type"
124124

125125
- do:
126126
allowed_warnings_regex:
@@ -190,7 +190,7 @@ unsupported:
190190
- match: { columns.28.type: integer }
191191

192192
- length: { values: 1 }
193-
- match: { values.0.0: null }
193+
- match: { values.0.0: '{ "max": 3.0, "min": 1.0, "sum": 10.1, "value_count": 5 }' }
194194
- match: { values.0.1: null }
195195
- match: { values.0.2: null }
196196
- match: { values.0.3: "2015-01-01T12:10:30.123456789Z" }

0 commit comments

Comments
 (0)