Skip to content

Commit e3bfec1

Browse files
authored
Add exponential histogram BlockLoader (elastic#137277)
1 parent 1f29688 commit e3bfec1

File tree

8 files changed

+472
-2
lines changed

8 files changed

+472
-2
lines changed

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,17 @@ interface BlockFactory {
511511
SortedSetOrdinalsBuilder sortedSetOrdinalsBuilder(SortedSetDocValues ordinals, int count);
512512

513513
AggregateMetricDoubleBuilder aggregateMetricDoubleBuilder(int count);
514+
515+
ExponentialHistogramBuilder exponentialHistogramBlockBuilder(int count);
516+
517+
Block buildExponentialHistogramBlockDirect(
518+
Block minima,
519+
Block maxima,
520+
Block sums,
521+
Block valueCounts,
522+
Block zeroThresholds,
523+
Block encodedHistograms
524+
);
514525
}
515526

516527
/**
@@ -643,4 +654,18 @@ interface AggregateMetricDoubleBuilder extends Builder {
643654

644655
IntBuilder count();
645656
}
657+
658+
interface ExponentialHistogramBuilder extends Builder {
659+
DoubleBuilder minima();
660+
661+
DoubleBuilder maxima();
662+
663+
DoubleBuilder sums();
664+
665+
LongBuilder valueCounts();
666+
667+
DoubleBuilder zeroThresholds();
668+
669+
BytesRefBuilder encodedHistograms();
670+
}
646671
}

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

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.apache.lucene.index.SortedSetDocValues;
1515
import org.apache.lucene.util.BytesRef;
1616
import org.elasticsearch.common.breaker.CircuitBreakingException;
17+
import org.elasticsearch.exponentialhistogram.CompressedExponentialHistogram;
1718
import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader;
1819
import org.hamcrest.Matcher;
1920

@@ -24,6 +25,7 @@
2425
import java.util.HashMap;
2526
import java.util.List;
2627
import java.util.stream.Collectors;
28+
import java.util.stream.IntStream;
2729

2830
import static org.elasticsearch.test.ESTestCase.assertThat;
2931
import static org.hamcrest.Matchers.equalTo;
@@ -446,6 +448,30 @@ public SortedSetOrdinalBuilder appendOrd(int value) {
446448
public BlockLoader.AggregateMetricDoubleBuilder aggregateMetricDoubleBuilder(int expectedSize) {
447449
return new AggregateMetricDoubleBlockBuilder(expectedSize);
448450
}
451+
452+
@Override
453+
public BlockLoader.ExponentialHistogramBuilder exponentialHistogramBlockBuilder(int count) {
454+
return new ExponentialHistogramBlockBuilder(this, count);
455+
}
456+
457+
@Override
458+
public BlockLoader.Block buildExponentialHistogramBlockDirect(
459+
BlockLoader.Block minima,
460+
BlockLoader.Block maxima,
461+
BlockLoader.Block sums,
462+
BlockLoader.Block valueCounts,
463+
BlockLoader.Block zeroThresholds,
464+
BlockLoader.Block encodedHistograms
465+
) {
466+
return ExponentialHistogramBlockBuilder.parseHistogramsToBlock(
467+
minima,
468+
maxima,
469+
sums,
470+
valueCounts,
471+
zeroThresholds,
472+
encodedHistograms
473+
);
474+
}
449475
};
450476
}
451477

@@ -658,4 +684,135 @@ public void close() {
658684

659685
}
660686
}
687+
688+
private static class ExponentialHistogramBlockBuilder implements BlockLoader.ExponentialHistogramBuilder {
689+
690+
private final BlockLoader.DoubleBuilder minima;
691+
private final BlockLoader.DoubleBuilder maxima;
692+
private final BlockLoader.DoubleBuilder sums;
693+
private final BlockLoader.LongBuilder valueCounts;
694+
private final BlockLoader.DoubleBuilder zeroThresholds;
695+
private final BlockLoader.BytesRefBuilder encodedHistograms;
696+
697+
private ExponentialHistogramBlockBuilder(BlockLoader.BlockFactory testFactory, int expectedSize) {
698+
minima = testFactory.doubles(expectedSize);
699+
maxima = testFactory.doubles(expectedSize);
700+
sums = testFactory.doubles(expectedSize);
701+
valueCounts = testFactory.longs(expectedSize);
702+
zeroThresholds = testFactory.doubles(expectedSize);
703+
encodedHistograms = testFactory.bytesRefs(expectedSize);
704+
}
705+
706+
@Override
707+
public BlockLoader.Block build() {
708+
BlockLoader.Block minimaBlock = minima.build();
709+
BlockLoader.Block maximaBlock = maxima.build();
710+
BlockLoader.Block sumsBlock = sums.build();
711+
BlockLoader.Block valueCountsBlock = valueCounts.build();
712+
BlockLoader.Block zeroThresholdsBlock = zeroThresholds.build();
713+
BlockLoader.Block encodedHistogramsBlock = encodedHistograms.build();
714+
return parseHistogramsToBlock(
715+
minimaBlock,
716+
maximaBlock,
717+
sumsBlock,
718+
valueCountsBlock,
719+
zeroThresholdsBlock,
720+
encodedHistogramsBlock
721+
);
722+
}
723+
724+
public static TestBlock parseHistogramsToBlock(
725+
BlockLoader.Block minimaBlock,
726+
BlockLoader.Block maximaBlock,
727+
BlockLoader.Block sumsBlock,
728+
BlockLoader.Block valueCountsBlock,
729+
BlockLoader.Block zeroThresholdsBlock,
730+
BlockLoader.Block encodedHistogramsBlock
731+
) {
732+
TestBlock minima = (TestBlock) minimaBlock;
733+
TestBlock maxima = (TestBlock) maximaBlock;
734+
TestBlock sums = (TestBlock) sumsBlock;
735+
TestBlock valueCounts = (TestBlock) valueCountsBlock;
736+
TestBlock zeroThresholds = (TestBlock) zeroThresholdsBlock;
737+
TestBlock encodedHistograms = (TestBlock) encodedHistogramsBlock;
738+
int count = minima.values.size();
739+
assert count == maxima.values.size();
740+
assert count == sums.values.size();
741+
assert count == valueCounts.values.size();
742+
assert count == zeroThresholds.values.size();
743+
assert count == encodedHistograms.values.size();
744+
745+
return new TestBlock(IntStream.range(0, count).mapToObj(i -> {
746+
if (encodedHistograms.get(i) == null) {
747+
return null;
748+
}
749+
CompressedExponentialHistogram result = new CompressedExponentialHistogram();
750+
try {
751+
Double min = (Double) minima.get(i);
752+
Double max = (Double) maxima.get(i);
753+
result.reset(
754+
(Double) zeroThresholds.get(i),
755+
(Long) valueCounts.get(i),
756+
(Double) sums.get(i),
757+
min == null ? Double.NaN : min,
758+
max == null ? Double.NaN : max,
759+
(BytesRef) encodedHistograms.get(i)
760+
);
761+
} catch (IOException e) {
762+
throw new RuntimeException(e);
763+
}
764+
return (Object) result;
765+
}).toList());
766+
}
767+
768+
@Override
769+
public BlockLoader.Builder appendNull() {
770+
throw new UnsupportedOperationException();
771+
}
772+
773+
@Override
774+
public BlockLoader.Builder beginPositionEntry() {
775+
throw new UnsupportedOperationException();
776+
}
777+
778+
@Override
779+
public BlockLoader.Builder endPositionEntry() {
780+
throw new UnsupportedOperationException();
781+
}
782+
783+
@Override
784+
public void close() {
785+
786+
}
787+
788+
@Override
789+
public BlockLoader.DoubleBuilder minima() {
790+
return minima;
791+
}
792+
793+
@Override
794+
public BlockLoader.DoubleBuilder maxima() {
795+
return maxima;
796+
}
797+
798+
@Override
799+
public BlockLoader.DoubleBuilder sums() {
800+
return sums;
801+
}
802+
803+
@Override
804+
public BlockLoader.LongBuilder valueCounts() {
805+
return valueCounts;
806+
}
807+
808+
@Override
809+
public BlockLoader.DoubleBuilder zeroThresholds() {
810+
return zeroThresholds;
811+
}
812+
813+
@Override
814+
public BlockLoader.BytesRefBuilder encodedHistograms() {
815+
return encodedHistograms;
816+
}
817+
}
661818
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.elasticsearch.common.util.BytesRefArray;
1616
import org.elasticsearch.compute.data.Block.MvOrdering;
1717
import org.elasticsearch.exponentialhistogram.ExponentialHistogram;
18+
import org.elasticsearch.index.mapper.BlockLoader;
1819

1920
import java.util.BitSet;
2021

@@ -481,6 +482,17 @@ public final ExponentialHistogramBlock newConstantExponentialHistogramBlock(Expo
481482
}
482483
}
483484

485+
public BlockLoader.Block newExponentialHistogramBlockFromDocValues(
486+
DoubleBlock minima,
487+
DoubleBlock maxima,
488+
DoubleBlock sums,
489+
LongBlock valueCounts,
490+
DoubleBlock zeroThresholds,
491+
BytesRefBlock encodedHistograms
492+
) {
493+
return new ExponentialHistogramArrayBlock(minima, maxima, sums, valueCounts, zeroThresholds, encodedHistograms);
494+
}
495+
484496
public final AggregateMetricDoubleBlock newAggregateMetricDoubleBlock(
485497
double[] minValues,
486498
double[] maxValues,
@@ -501,4 +513,5 @@ public final AggregateMetricDoubleBlock newAggregateMetricDoubleBlock(
501513
public long maxPrimitiveArrayBytes() {
502514
return maxPrimitiveArrayBytes;
503515
}
516+
504517
}

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

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
import org.elasticsearch.exponentialhistogram.CompressedExponentialHistogram;
1313
import org.elasticsearch.exponentialhistogram.ExponentialHistogram;
1414
import org.elasticsearch.exponentialhistogram.ZeroBucket;
15+
import org.elasticsearch.index.mapper.BlockLoader;
1516

1617
import java.io.IOException;
1718

18-
public class ExponentialHistogramBlockBuilder implements Block.Builder {
19+
public class ExponentialHistogramBlockBuilder implements Block.Builder, BlockLoader.ExponentialHistogramBuilder {
1920

2021
private final DoubleBlock.Builder minimaBuilder;
2122
private final DoubleBlock.Builder maximaBuilder;
@@ -60,6 +61,36 @@ public class ExponentialHistogramBlockBuilder implements Block.Builder {
6061
}
6162
}
6263

64+
@Override
65+
public BlockLoader.DoubleBuilder minima() {
66+
return minimaBuilder;
67+
}
68+
69+
@Override
70+
public BlockLoader.DoubleBuilder maxima() {
71+
return maximaBuilder;
72+
}
73+
74+
@Override
75+
public BlockLoader.DoubleBuilder sums() {
76+
return sumsBuilder;
77+
}
78+
79+
@Override
80+
public BlockLoader.LongBuilder valueCounts() {
81+
return valueCountsBuilder;
82+
}
83+
84+
@Override
85+
public BlockLoader.DoubleBuilder zeroThresholds() {
86+
return zeroThresholdsBuilder;
87+
}
88+
89+
@Override
90+
public BlockLoader.BytesRefBuilder encodedHistograms() {
91+
return encodedHistogramsBuilder;
92+
}
93+
6394
public ExponentialHistogramBlockBuilder append(ExponentialHistogram histogram) {
6495
assert histogram != null;
6596
// TODO: fix performance and correctness before using in production code

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
import org.elasticsearch.compute.data.BlockFactory;
1616
import org.elasticsearch.compute.data.BytesRefBlock;
1717
import org.elasticsearch.compute.data.BytesRefVector;
18+
import org.elasticsearch.compute.data.DoubleBlock;
1819
import org.elasticsearch.compute.data.ElementType;
1920
import org.elasticsearch.compute.data.IntVector;
21+
import org.elasticsearch.compute.data.LongBlock;
2022
import org.elasticsearch.compute.data.OrdinalBytesRefVector;
2123
import org.elasticsearch.core.Releasables;
2224
import org.elasticsearch.index.mapper.BlockLoader;
@@ -148,4 +150,28 @@ public BlockLoader.SortedSetOrdinalsBuilder sortedSetOrdinalsBuilder(SortedSetDo
148150
public BlockLoader.AggregateMetricDoubleBuilder aggregateMetricDoubleBuilder(int count) {
149151
return factory.newAggregateMetricDoubleBlockBuilder(count);
150152
}
153+
154+
@Override
155+
public BlockLoader.ExponentialHistogramBuilder exponentialHistogramBlockBuilder(int count) {
156+
return factory.newExponentialHistogramBlockBuilder(count);
157+
}
158+
159+
@Override
160+
public BlockLoader.Block buildExponentialHistogramBlockDirect(
161+
BlockLoader.Block minima,
162+
BlockLoader.Block maxima,
163+
BlockLoader.Block sums,
164+
BlockLoader.Block valueCounts,
165+
BlockLoader.Block zeroThresholds,
166+
BlockLoader.Block encodedHistograms
167+
) {
168+
return factory.newExponentialHistogramBlockFromDocValues(
169+
(DoubleBlock) minima,
170+
(DoubleBlock) maxima,
171+
(DoubleBlock) sums,
172+
(LongBlock) valueCounts,
173+
(DoubleBlock) zeroThresholds,
174+
(BytesRefBlock) encodedHistograms
175+
);
176+
}
151177
}

x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/AllSupportedFieldsTestCase.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,8 @@ private static boolean supportedInIndex(DataType t) {
579579
UNSUPPORTED, PARTIAL_AGG,
580580
// You can't index these - they are just constants.
581581
DATE_PERIOD, TIME_DURATION, GEOTILE, GEOHASH, GEOHEX,
582-
// TODO(b/133393): BlockLoader for EXPONENTIAL_HISTOGRAM is not implemented yet
582+
// TODO(b/133393): Once we remove the feature-flag of the exp-histo field type (!= ES|QL type),
583+
// replace this with a capability check
583584
EXPONENTIAL_HISTOGRAM,
584585
// TODO fix geo
585586
CARTESIAN_POINT, CARTESIAN_SHAPE -> false;

0 commit comments

Comments
 (0)