Skip to content

Commit c12cf21

Browse files
committed
[ES|QL] Support some stats on aggregate_double_metric
Adds support for min, max, sum, and count
1 parent 9782179 commit c12cf21

File tree

28 files changed

+628
-101
lines changed

28 files changed

+628
-101
lines changed

server/src/main/java/org/elasticsearch/index/mapper/BlockLoader.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ interface BlockFactory {
417417
SingletonOrdinalsBuilder singletonOrdinalsBuilder(SortedDocValues ordinals, int count);
418418

419419
// TODO support non-singleton ords
420+
421+
AggregateDoubleMetricBuilder aggregateDoubleMetricBuilder(int count);
420422
}
421423

422424
/**
@@ -501,4 +503,10 @@ interface SingletonOrdinalsBuilder extends Builder {
501503
*/
502504
SingletonOrdinalsBuilder appendOrd(int value);
503505
}
506+
507+
interface AggregateDoubleMetricBuilder extends Builder {
508+
509+
AggregateDoubleMetricBuilder append(double min, double max, double sum, int valueCount);
510+
511+
}
504512
}

test/framework/src/main/java/org/elasticsearch/index/mapper/TestBlock.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ public SingletonOrdsBuilder appendOrd(int value) {
147147
}
148148
return new SingletonOrdsBuilder();
149149
}
150+
151+
@Override
152+
public BlockLoader.AggregateDoubleMetricBuilder aggregateDoubleMetricBuilder(int count) {
153+
return null;
154+
}
150155
};
151156
}
152157

x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/plugin/EsqlCorePlugin.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@
1414
public class EsqlCorePlugin extends Plugin implements ExtensiblePlugin {
1515

1616
public static final FeatureFlag SEMANTIC_TEXT_FEATURE_FLAG = new FeatureFlag("esql_semantic_text");
17+
public static final FeatureFlag AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG = new FeatureFlag("esql_aggregate_metric_double");
1718
}

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,9 @@ public enum DataType {
307307
* loaded from the index and ESQL will load these fields as strings without their attached
308308
* chunks or embeddings.
309309
*/
310-
SEMANTIC_TEXT(builder().esType("semantic_text").unknownSize());
310+
SEMANTIC_TEXT(builder().esType("semantic_text").unknownSize()),
311+
312+
AGGREGATE_METRIC_DOUBLE(builder().esType("aggregate_metric_double").unknownSize());
311313

312314
/**
313315
* Types that are actively being built. These types are not returned
@@ -316,7 +318,8 @@ public enum DataType {
316318
* check that sending them to a function produces a sane error message.
317319
*/
318320
public static final Map<DataType, FeatureFlag> UNDER_CONSTRUCTION = Map.ofEntries(
319-
Map.entry(SEMANTIC_TEXT, EsqlCorePlugin.SEMANTIC_TEXT_FEATURE_FLAG)
321+
Map.entry(SEMANTIC_TEXT, EsqlCorePlugin.SEMANTIC_TEXT_FEATURE_FLAG),
322+
Map.entry(AGGREGATE_METRIC_DOUBLE, EsqlCorePlugin.AGGREGATE_METRIC_DOUBLE_FEATURE_FLAG)
320323
);
321324

322325
private final String typeName;
@@ -553,6 +556,7 @@ public static boolean isRepresentable(DataType t) {
553556
&& t != SOURCE
554557
&& t != HALF_FLOAT
555558
&& t != PARTIAL_AGG
559+
&& t != AGGREGATE_METRIC_DOUBLE
556560
&& t.isCounter() == false;
557561
}
558562

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
package org.elasticsearch.compute.data;
9+
10+
import org.elasticsearch.index.mapper.BlockLoader;
11+
12+
public class AggregateDoubleMetricBlockBuilder extends AbstractBlockBuilder implements BlockLoader.AggregateDoubleMetricBuilder {
13+
14+
private final DoubleBlockBuilder minBuilder;
15+
private final DoubleBlockBuilder maxBuilder;
16+
private final DoubleBlockBuilder sumBuilder;
17+
private final IntBlockBuilder countBuilder;
18+
19+
public AggregateDoubleMetricBlockBuilder(int estimatedSize, BlockFactory blockFactory) {
20+
super(blockFactory);
21+
minBuilder = new DoubleBlockBuilder(estimatedSize, blockFactory);
22+
maxBuilder = new DoubleBlockBuilder(estimatedSize, blockFactory);
23+
sumBuilder = new DoubleBlockBuilder(estimatedSize, blockFactory);
24+
countBuilder = new IntBlockBuilder(estimatedSize, blockFactory);
25+
}
26+
27+
@Override
28+
protected int valuesLength() {
29+
return minBuilder.valuesLength();
30+
}
31+
32+
@Override
33+
protected void growValuesArray(int newSize) {
34+
minBuilder.growValuesArray(newSize);
35+
maxBuilder.growValuesArray(newSize);
36+
sumBuilder.growValuesArray(newSize);
37+
countBuilder.growValuesArray(newSize);
38+
}
39+
40+
@Override
41+
protected int elementSize() {
42+
return minBuilder.elementSize() + maxBuilder.elementSize() + sumBuilder.elementSize() + countBuilder.elementSize();
43+
}
44+
45+
@Override
46+
public Block.Builder copyFrom(Block block, int beginInclusive, int endExclusive) {
47+
CompositeBlock composite = (CompositeBlock) block;
48+
minBuilder.copyFrom(composite.getBlock(Metric.MIN.ordinal()), beginInclusive, endExclusive);
49+
maxBuilder.copyFrom(composite.getBlock(Metric.MAX.ordinal()), beginInclusive, endExclusive);
50+
sumBuilder.copyFrom(composite.getBlock(Metric.SUM.ordinal()), beginInclusive, endExclusive);
51+
countBuilder.copyFrom(composite.getBlock(Metric.COUNT.ordinal()), beginInclusive, endExclusive);
52+
return this;
53+
}
54+
55+
@Override
56+
public Block.Builder mvOrdering(Block.MvOrdering mvOrdering) {
57+
minBuilder.mvOrdering(mvOrdering);
58+
maxBuilder.mvOrdering(mvOrdering);
59+
sumBuilder.mvOrdering(mvOrdering);
60+
countBuilder.mvOrdering(mvOrdering);
61+
return this;
62+
}
63+
64+
@Override
65+
public Block build() {
66+
Block[] blocks = new Block[4];
67+
blocks[Metric.MIN.ordinal()] = minBuilder.build();
68+
blocks[Metric.MAX.ordinal()] = maxBuilder.build();
69+
blocks[Metric.SUM.ordinal()] = sumBuilder.build();
70+
blocks[Metric.COUNT.ordinal()] = countBuilder.build();
71+
return new CompositeBlock(blocks);
72+
}
73+
74+
@Override
75+
public BlockLoader.AggregateDoubleMetricBuilder append(double min, double max, double sum, int valueCount) {
76+
minBuilder.appendDouble(min);
77+
maxBuilder.appendDouble(max);
78+
sumBuilder.appendDouble(sum);
79+
countBuilder.appendInt(valueCount);
80+
return this;
81+
}
82+
83+
public enum Metric {
84+
MIN,
85+
MAX,
86+
SUM,
87+
COUNT;
88+
}
89+
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,10 @@ public Block newConstantNullBlock(int positions) {
432432
return b;
433433
}
434434

435+
public AggregateDoubleMetricBlockBuilder newAggregatedDoubleMetricBlockBuilder(int estimatedSize) {
436+
return new AggregateDoubleMetricBlockBuilder(estimatedSize, this);
437+
}
438+
435439
/**
436440
* Returns the maximum number of bytes that a Block should be backed by a primitive array before switching to using BigArrays.
437441
*/

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,22 +86,30 @@ public int getPositionCount() {
8686

8787
@Override
8888
public int getTotalValueCount() {
89-
throw new UnsupportedOperationException("Composite block");
89+
// TODO: this works for aggregate metric double fields, because the four blocks are guarenteed to have the same length / positions.
90+
// So check just for one sub block is sufficient.
91+
return blocks[0].getTotalValueCount();
9092
}
9193

9294
@Override
9395
public int getFirstValueIndex(int position) {
94-
throw new UnsupportedOperationException("Composite block");
96+
// TODO: this works for aggregate metric double fields, because the four blocks are guarenteed to have the same length / positions.
97+
// So check just for one sub block is sufficient.
98+
return blocks[0].getFirstValueIndex(position);
9599
}
96100

97101
@Override
98102
public int getValueCount(int position) {
99-
throw new UnsupportedOperationException("Composite block");
103+
// TODO: this works for aggregate metric double fields, because the four blocks are guarenteed to have the same length / positions.
104+
// So check just for one sub block is sufficient.
105+
return blocks[0].getValueCount(position);
100106
}
101107

102108
@Override
103109
public boolean isNull(int position) {
104-
throw new UnsupportedOperationException("Composite block");
110+
// TODO: this works for aggregate metric double fields, because the four blocks are guarenteed to have the same length / positions.
111+
// So check just for one sub block is sufficient.
112+
return blocks[0].isNull(position);
105113
}
106114

107115
@Override

x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/lucene/ValuesSourceReaderOperator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,11 @@ public BytesRefBlock constantBytes(BytesRef value) {
698698
public BlockLoader.SingletonOrdinalsBuilder singletonOrdinalsBuilder(SortedDocValues ordinals, int count) {
699699
return new SingletonOrdinalsBuilder(factory, ordinals, count);
700700
}
701+
702+
@Override
703+
public BlockLoader.AggregateDoubleMetricBuilder aggregateDoubleMetricBuilder(int count) {
704+
return factory.newAggregatedDoubleMetricBlockBuilder(count);
705+
}
701706
}
702707

703708
// TODO tests that mix source loaded fields and doc values in the same block

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -765,9 +765,8 @@ public static Literal randomLiteral(DataType type) {
765765
throw new UncheckedIOException(e);
766766
}
767767
}
768-
case UNSUPPORTED, OBJECT, DOC_DATA_TYPE, TSID_DATA_TYPE, PARTIAL_AGG -> throw new IllegalArgumentException(
769-
"can't make random values for [" + type.typeName() + "]"
770-
);
768+
case UNSUPPORTED, OBJECT, DOC_DATA_TYPE, TSID_DATA_TYPE, PARTIAL_AGG, AGGREGATE_METRIC_DOUBLE ->
769+
throw new IllegalArgumentException("can't make random values for [" + type.typeName() + "]");
771770
}, type);
772771
}
773772

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
@@ -733,7 +733,12 @@ public enum Cap {
733733
/**
734734
* Support named argument for function in map format.
735735
*/
736-
OPTIONAL_NAMED_ARGUMENT_MAP_FOR_FUNCTION(Build.current().isSnapshot());
736+
OPTIONAL_NAMED_ARGUMENT_MAP_FOR_FUNCTION(Build.current().isSnapshot()),
737+
738+
/**
739+
* Support for aggregate_metric_double type
740+
*/
741+
AGGREGATE_METRIC_DOUBLE;
737742

738743
private final boolean enabled;
739744

0 commit comments

Comments
 (0)