Skip to content

Commit 1071983

Browse files
authored
[ES|QL] Add ToAggregateMetricDouble example (#125518)
Adds AggregateMetricDouble to the ES|QL CSV tests and examples of how to use the ToAggregateMetricDouble function
1 parent 632b9e7 commit 1071983

File tree

10 files changed

+146
-3
lines changed

10 files changed

+146
-3
lines changed

docs/reference/query-languages/esql/_snippets/functions/examples/to_aggregate_metric_double.md

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/_snippets/functions/layout/to_aggregate_metric_double.md

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/_snippets/functions/parameters/to_aggregate_metric_double.md

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/definition/functions/to_aggregate_metric_double.json

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/reference/query-languages/esql/kibana/docs/functions/to_aggregate_metric_double.md

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvAssert.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.apache.lucene.util.BytesRef;
1111
import org.elasticsearch.common.Strings;
1212
import org.elasticsearch.common.time.DateFormatter;
13+
import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder;
1314
import org.elasticsearch.compute.data.Page;
1415
import org.elasticsearch.logging.Logger;
1516
import org.elasticsearch.search.DocValueFormat;
@@ -40,6 +41,7 @@
4041
import static org.elasticsearch.xpack.esql.core.util.NumericUtils.unsignedLongAsNumber;
4142
import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.CARTESIAN;
4243
import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO;
44+
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.aggregateMetricDoubleLiteralToString;
4345
import static org.hamcrest.MatcherAssert.assertThat;
4446
import static org.hamcrest.Matchers.instanceOf;
4547
import static org.junit.Assert.assertEquals;
@@ -409,6 +411,11 @@ private static Object convertExpectedValue(Type expectedType, Object expectedVal
409411
case Type.VERSION -> // convert BytesRef-packed Version to String
410412
rebuildExpected(expectedValue, BytesRef.class, x -> new Version((BytesRef) x).toString());
411413
case UNSIGNED_LONG -> rebuildExpected(expectedValue, Long.class, x -> unsignedLongAsNumber((long) x));
414+
case AGGREGATE_METRIC_DOUBLE -> rebuildExpected(
415+
expectedValue,
416+
AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral.class,
417+
x -> aggregateMetricDoubleLiteralToString((AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral) x)
418+
);
412419
default -> expectedValue;
413420
};
414421
}

x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestUtils.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.elasticsearch.common.time.DateFormatters;
1616
import org.elasticsearch.common.time.DateUtils;
1717
import org.elasticsearch.common.util.BigArrays;
18+
import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder;
1819
import org.elasticsearch.compute.data.Block;
1920
import org.elasticsearch.compute.data.BlockFactory;
2021
import org.elasticsearch.compute.data.BlockUtils;
@@ -62,6 +63,7 @@
6263
import static org.elasticsearch.xpack.esql.core.util.NumericUtils.asLongUnsigned;
6364
import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.CARTESIAN;
6465
import static org.elasticsearch.xpack.esql.core.util.SpatialCoordinateTypes.GEO;
66+
import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.stringToAggregateMetricDoubleLiteral;
6567

6668
public final class CsvTestUtils {
6769
private static final int MAX_WIDTH = 80;
@@ -480,6 +482,10 @@ public enum Type {
480482
CARTESIAN_POINT(x -> x == null ? null : CARTESIAN.wktToWkb(x), BytesRef.class),
481483
GEO_SHAPE(x -> x == null ? null : GEO.wktToWkb(x), BytesRef.class),
482484
CARTESIAN_SHAPE(x -> x == null ? null : CARTESIAN.wktToWkb(x), BytesRef.class),
485+
AGGREGATE_METRIC_DOUBLE(
486+
x -> x == null ? null : stringToAggregateMetricDoubleLiteral(x),
487+
AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral.class
488+
),
483489
UNSUPPORTED(Type::convertUnsupported, Void.class);
484490

485491
private static Void convertUnsupported(String s) {
@@ -560,11 +566,18 @@ public static Type asType(ElementType elementType, Type actualType) {
560566
case BYTES_REF -> bytesRefBlockType(actualType);
561567
case BOOLEAN -> BOOLEAN;
562568
case DOC -> throw new IllegalArgumentException("can't assert on doc blocks");
563-
case COMPOSITE -> throw new IllegalArgumentException("can't assert on composite blocks");
569+
case COMPOSITE -> compositeBlockType(actualType);
564570
case UNKNOWN -> throw new IllegalArgumentException("Unknown block types cannot be handled");
565571
};
566572
}
567573

574+
private static Type compositeBlockType(Type actualType) {
575+
return switch (actualType) {
576+
case AGGREGATE_METRIC_DOUBLE -> actualType;
577+
default -> throw new IllegalArgumentException("can't assert on composite blocks that aren't aggregate metric doubles");
578+
};
579+
}
580+
568581
private static Type bytesRefBlockType(Type actualType) {
569582
return switch (actualType) {
570583
case NULL -> NULL;

x-pack/plugin/esql/qa/testFixtures/src/main/resources/convert.csv-spec

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,3 +453,31 @@ emp_no:integer | birth_date:datetime
453453
10097 | 1952-02-27T00:00:00.000Z
454454
10100 | 1953-04-21T00:00:00.000Z
455455
;
456+
457+
convertToAggregateMetricDouble
458+
required_capability: aggregate_metric_double_convert_to
459+
//tag::toAggregateMetricDouble[]
460+
ROW x = 3892095203
461+
| EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(x)
462+
//end::toAggregateMetricDouble[]
463+
;
464+
465+
//tag::toAggregateMetricDouble-result[]
466+
x:long | agg_metric:aggregate_metric_double
467+
3892095203 | {"min":3892095203.0,"max":3892095203.0,"sum":3892095203.0,"value_count":1}
468+
//end::toAggregateMetricDouble-result[]
469+
;
470+
471+
convertToAggregateMetricDoubleMv
472+
required_capability: aggregate_metric_double_convert_to
473+
//tag::toAggregateMetricDoubleMv[]
474+
ROW x = [5032, 11111, 40814]
475+
| EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(x)
476+
//end::toAggregateMetricDoubleMv[]
477+
;
478+
479+
//tag::toAggregateMetricDoubleMv-result[]
480+
x:integer | agg_metric:aggregate_metric_double
481+
[5032, 11111, 40814] | {"min":5032.0,"max":40814.0,"sum":56957.0,"value_count":3}
482+
//end::toAggregateMetricDoubleMv-result[]
483+
;

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/convert/ToAggregateMetricDouble.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.elasticsearch.xpack.esql.core.tree.NodeInfo;
3131
import org.elasticsearch.xpack.esql.core.tree.Source;
3232
import org.elasticsearch.xpack.esql.core.type.DataType;
33+
import org.elasticsearch.xpack.esql.expression.function.Example;
3334
import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesTo;
3435
import org.elasticsearch.xpack.esql.expression.function.FunctionAppliesToLifecycle;
3536
import org.elasticsearch.xpack.esql.expression.function.FunctionInfo;
@@ -67,14 +68,17 @@ public class ToAggregateMetricDouble extends AbstractConvertFunction {
6768
@FunctionInfo(
6869
returnType = "aggregate_metric_double",
6970
description = "Encode a numeric to an aggregate_metric_double.",
71+
examples = {
72+
@Example(file = "convert", tag = "toAggregateMetricDouble"),
73+
@Example(description = "The expression also accepts multi-values", file = "convert", tag = "toAggregateMetricDoubleMv") },
7074
appliesTo = { @FunctionAppliesTo(lifeCycle = FunctionAppliesToLifecycle.COMING, version = "9.1") }
7175
)
7276
public ToAggregateMetricDouble(
7377
Source source,
7478
@Param(
7579
name = "number",
7680
type = { "double", "long", "unsigned_long", "integer", "aggregate_metric_double" },
77-
description = "Input value. The input can be a single-valued column or an expression."
81+
description = "Input value. The input can be a single- or multi-valued column or an expression."
7882
) Expression field
7983
) {
8084
super(source, field);

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

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.elasticsearch.common.time.DateFormatter;
1717
import org.elasticsearch.common.time.DateFormatters;
1818
import org.elasticsearch.common.time.DateUtils;
19+
import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder;
1920
import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder.Metric;
2021
import org.elasticsearch.compute.data.CompositeBlock;
2122
import org.elasticsearch.compute.data.DoubleBlock;
@@ -701,6 +702,60 @@ public static String aggregateMetricDoubleBlockToString(CompositeBlock composite
701702
}
702703
}
703704

705+
public static String aggregateMetricDoubleLiteralToString(AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral aggMetric) {
706+
try (XContentBuilder builder = JsonXContent.contentBuilder()) {
707+
builder.startObject();
708+
if (aggMetric.min() != null) {
709+
builder.field(Metric.MIN.getLabel(), aggMetric.min());
710+
}
711+
if (aggMetric.max() != null) {
712+
builder.field(Metric.MAX.getLabel(), aggMetric.max());
713+
}
714+
if (aggMetric.sum() != null) {
715+
builder.field(Metric.SUM.getLabel(), aggMetric.sum());
716+
}
717+
if (aggMetric.count() != null) {
718+
builder.field(Metric.COUNT.getLabel(), aggMetric.count());
719+
}
720+
builder.endObject();
721+
return Strings.toString(builder);
722+
} catch (IOException e) {
723+
throw new IllegalStateException("error rendering aggregate metric double", e);
724+
}
725+
}
726+
727+
public static AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral stringToAggregateMetricDoubleLiteral(String s) {
728+
Double min = null;
729+
Double max = null;
730+
Double sum = null;
731+
Integer count = null;
732+
String[] values = s.substring(1, s.length() - 1).split(",");
733+
for (String v : values) {
734+
var pair = v.split(":");
735+
String type = pair[0];
736+
String number = pair[1];
737+
switch (type) {
738+
case "min":
739+
min = Double.parseDouble(number);
740+
break;
741+
case "max":
742+
max = Double.parseDouble(number);
743+
break;
744+
case "sum":
745+
sum = Double.parseDouble(number);
746+
break;
747+
case "value_count":
748+
count = Integer.parseInt(number);
749+
break;
750+
default:
751+
throw new IllegalArgumentException(
752+
"Received a metric that wasn't min, max, sum, or value_count: " + type + " with value: " + number
753+
);
754+
}
755+
}
756+
return new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral(min, max, sum, count);
757+
}
758+
704759
public enum EsqlConverter implements Converter {
705760

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

0 commit comments

Comments
 (0)