Skip to content

Commit f6b5080

Browse files
committed
[ES|QL] Add ToAggregateMetricDouble example (elastic#125518)
Adds AggregateMetricDouble to the ES|QL CSV tests and examples of how to use the ToAggregateMetricDouble function
1 parent 5e86d0e commit f6b5080

File tree

9 files changed

+171
-3
lines changed

9 files changed

+171
-3
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
2+
3+
## `TO_AGGREGATE_METRIC_DOUBLE` [esql-to_aggregate_metric_double]
4+
```{applies_to}
5+
product: COMING 9.1
6+
```
7+
8+
**Syntax**
9+
10+
:::{image} ../../../images/functions/to_aggregate_metric_double.svg
11+
:alt: Embedded
12+
:class: text-center
13+
:::
14+
15+
16+
:::{include} ../parameters/to_aggregate_metric_double.md
17+
:::
18+
19+
:::{include} ../description/to_aggregate_metric_double.md
20+
:::
21+
22+
:::{include} ../types/to_aggregate_metric_double.md
23+
:::
24+
25+
:::{include} ../examples/to_aggregate_metric_double.md
26+
:::
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
% This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
2+
3+
**Parameters**
4+
5+
`number`
6+
: Input value. The input can be a single- or multi-valued column or an expression.
7+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"comment" : "This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.",
3+
"type" : "scalar",
4+
"name" : "to_aggregate_metric_double",
5+
"description" : "Encode a numeric to an aggregate_metric_double.",
6+
"signatures" : [ ],
7+
"examples" : [
8+
"ROW x = 3892095203\n| EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(x)",
9+
"ROW x = [5032, 11111, 40814]\n| EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(x)"
10+
],
11+
"preview" : false,
12+
"snapshot_only" : false
13+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!--
2+
This is generated by ESQL’s AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.
3+
-->
4+
5+
### TO_AGGREGATE_METRIC_DOUBLE
6+
Encode a numeric to an aggregate_metric_double.
7+
8+
```
9+
ROW x = 3892095203
10+
| EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(x)
11+
```

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;
@@ -405,6 +407,11 @@ private static Object convertExpectedValue(Type expectedType, Object expectedVal
405407
case VERSION -> // convert BytesRef-packed Version to String
406408
rebuildExpected(expectedValue, BytesRef.class, x -> new Version((BytesRef) x).toString());
407409
case UNSIGNED_LONG -> rebuildExpected(expectedValue, Long.class, x -> unsignedLongAsNumber((long) x));
410+
case AGGREGATE_METRIC_DOUBLE -> rebuildExpected(
411+
expectedValue,
412+
AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral.class,
413+
x -> aggregateMetricDoubleLiteralToString((AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral) x)
414+
);
408415
default -> expectedValue;
409416
};
410417
}

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
@@ -451,3 +451,31 @@ emp_no:integer | birth_date:datetime
451451
10097 | 1952-02-27T00:00:00.000Z
452452
10100 | 1953-04-21T00:00:00.000Z
453453
;
454+
455+
convertToAggregateMetricDouble
456+
required_capability: aggregate_metric_double_convert_to
457+
//tag::toAggregateMetricDouble[]
458+
ROW x = 3892095203
459+
| EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(x)
460+
//end::toAggregateMetricDouble[]
461+
;
462+
463+
//tag::toAggregateMetricDouble-result[]
464+
x:long | agg_metric:aggregate_metric_double
465+
3892095203 | {"min":3892095203.0,"max":3892095203.0,"sum":3892095203.0,"value_count":1}
466+
//end::toAggregateMetricDouble-result[]
467+
;
468+
469+
convertToAggregateMetricDoubleMv
470+
required_capability: aggregate_metric_double_convert_to
471+
//tag::toAggregateMetricDoubleMv[]
472+
ROW x = [5032, 11111, 40814]
473+
| EVAL agg_metric = TO_AGGREGATE_METRIC_DOUBLE(x)
474+
//end::toAggregateMetricDoubleMv[]
475+
;
476+
477+
//tag::toAggregateMetricDoubleMv-result[]
478+
x:integer | agg_metric:aggregate_metric_double
479+
[5032, 11111, 40814] | {"min":5032.0,"max":40814.0,"sum":56957.0,"value_count":3}
480+
//end::toAggregateMetricDoubleMv-result[]
481+
;

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

Lines changed: 10 additions & 2 deletions
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.FunctionInfo;
3435
import org.elasticsearch.xpack.esql.expression.function.Param;
3536
import org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter;
@@ -62,13 +63,20 @@ public class ToAggregateMetricDouble extends AbstractConvertFunction {
6263
ToAggregateMetricDouble::new
6364
);
6465

65-
@FunctionInfo(returnType = "aggregate_metric_double", description = "Encode a numeric to an aggregate_metric_double.")
66+
@FunctionInfo(
67+
returnType = "aggregate_metric_double",
68+
description = "Encode a numeric to an aggregate_metric_double.",
69+
examples = {
70+
@Example(file = "convert", tag = "toAggregateMetricDouble"),
71+
@Example(description = "The expression also accepts multi-values", file = "convert", tag = "toAggregateMetricDoubleMv")
72+
}
73+
)
6674
public ToAggregateMetricDouble(
6775
Source source,
6876
@Param(
6977
name = "number",
7078
type = { "double", "long", "unsigned_long", "integer", "aggregate_metric_double" },
71-
description = "Input value. The input can be a single-valued column or an expression."
79+
description = "Input value. The input can be a single- or multi-valued column or an expression."
7280
) Expression field
7381
) {
7482
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;
@@ -708,6 +709,60 @@ public static String aggregateMetricDoubleBlockToString(CompositeBlock composite
708709
}
709710
}
710711

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

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

0 commit comments

Comments
 (0)