From 75c06d290218cc724e992bb74f6d2f8f761b9195 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Tue, 4 Nov 2025 18:21:17 -0500 Subject: [PATCH 1/6] WIP --- ...stractDoublesFromDocValuesBlockLoader.java | 165 ++++++++++++++++++ ...AbstractLongsFromDocValuesBlockLoader.java | 159 +++++++++++++++++ .../docvalues/DoublesBlockLoader.java | 143 +-------------- .../docvalues/LongsBlockLoader.java | 137 +-------------- .../index/mapper/DateFieldMapperTests.java | 8 +- .../index/mapper/MapperTestCase.java | 8 +- .../read/ValuesSourceReaderOperatorTests.java | 6 +- 7 files changed, 352 insertions(+), 274 deletions(-) create mode 100644 server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractDoublesFromDocValuesBlockLoader.java create mode 100644 server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractLongsFromDocValuesBlockLoader.java diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractDoublesFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractDoublesFromDocValuesBlockLoader.java new file mode 100644 index 0000000000000..39a8727a8df8f --- /dev/null +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractDoublesFromDocValuesBlockLoader.java @@ -0,0 +1,165 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues; + +import org.apache.lucene.index.DocValues; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.SortedNumericDocValues; + +import java.io.IOException; + +/** + * Loads {@code double}s from doc values. + */ +public abstract class AbstractDoublesFromDocValuesBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { + protected final String fieldName; + private final BlockDocValuesReader.ToDouble toDouble; + + public AbstractDoublesFromDocValuesBlockLoader(String fieldName, BlockDocValuesReader.ToDouble toDouble) { + this.fieldName = fieldName; + this.toDouble = toDouble; + } + + @Override + public final Builder builder(BlockFactory factory, int expectedCount) { + return factory.doubles(expectedCount); + } + + @Override + public final AllReader reader(LeafReaderContext context) throws IOException { + SortedNumericDocValues docValues = context.reader().getSortedNumericDocValues(fieldName); + if (docValues != null) { + NumericDocValues singleton = DocValues.unwrapSingleton(docValues); + if (singleton != null) { + return singletonReader(singleton, toDouble); + } + return sortedReader(docValues, toDouble); + } + NumericDocValues singleton = context.reader().getNumericDocValues(fieldName); + if (singleton != null) { + return singletonReader(singleton, toDouble); + } + return new ConstantNullsReader(); + } + + protected abstract AllReader singletonReader(NumericDocValues docValues, BlockDocValuesReader.ToDouble toDouble); + + protected abstract AllReader sortedReader(SortedNumericDocValues docValues, BlockDocValuesReader.ToDouble toDouble); + + public static class Singleton extends BlockDocValuesReader implements BlockDocValuesReader.NumericDocValuesAccessor { + private final NumericDocValues docValues; + private final ToDouble toDouble; + + Singleton(NumericDocValues docValues, ToDouble toDouble) { + this.docValues = docValues; + this.toDouble = toDouble; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + if (docValues instanceof OptionalColumnAtATimeReader direct) { + Block result = direct.tryRead(factory, docs, offset, nullsFiltered, toDouble, false); + if (result != null) { + return result; + } + } + try (DoubleBuilder builder = factory.doublesFromDocValues(docs.count() - offset)) { + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + if (docValues.advanceExact(doc)) { + builder.appendDouble(toDouble.convert(docValues.longValue())); + } else { + builder.appendNull(); + } + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + DoubleBuilder blockBuilder = (DoubleBuilder) builder; + if (docValues.advanceExact(docId)) { + blockBuilder.appendDouble(toDouble.convert(docValues.longValue())); + } else { + blockBuilder.appendNull(); + } + } + + @Override + public int docId() { + return docValues.docID(); + } + + @Override + public String toString() { + return "DoublesFromDocValues.Singleton"; + } + + @Override + public NumericDocValues numericDocValues() { + return docValues; + } + } + + public static class Sorted extends BlockDocValuesReader { + private final SortedNumericDocValues docValues; + private final ToDouble toDouble; + + Sorted(SortedNumericDocValues docValues, ToDouble toDouble) { + this.docValues = docValues; + this.toDouble = toDouble; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + try (DoubleBuilder builder = factory.doublesFromDocValues(docs.count() - offset)) { + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + read(doc, builder); + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + read(docId, (DoubleBuilder) builder); + } + + private void read(int doc, DoubleBuilder builder) throws IOException { + if (false == docValues.advanceExact(doc)) { + builder.appendNull(); + return; + } + int count = docValues.docValueCount(); + if (count == 1) { + builder.appendDouble(toDouble.convert(docValues.nextValue())); + return; + } + builder.beginPositionEntry(); + for (int v = 0; v < count; v++) { + builder.appendDouble(toDouble.convert(docValues.nextValue())); + } + builder.endPositionEntry(); + } + + @Override + public int docId() { + return docValues.docID(); + } + + @Override + public String toString() { + return "LongsFromDocValues.Sorted"; + } + } +} diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractLongsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractLongsFromDocValuesBlockLoader.java new file mode 100644 index 0000000000000..c4d981329f6bd --- /dev/null +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractLongsFromDocValuesBlockLoader.java @@ -0,0 +1,159 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues; + +import org.apache.lucene.index.DocValues; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.SortedNumericDocValues; + +import java.io.IOException; + +/** + * Loads {@code long}s from doc values. + */ +public abstract class AbstractLongsFromDocValuesBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { + protected final String fieldName; + + public AbstractLongsFromDocValuesBlockLoader(String fieldName) { + this.fieldName = fieldName; + } + + @Override + public final Builder builder(BlockFactory factory, int expectedCount) { + return factory.longs(expectedCount); + } + + @Override + public final AllReader reader(LeafReaderContext context) throws IOException { + SortedNumericDocValues docValues = context.reader().getSortedNumericDocValues(fieldName); + if (docValues != null) { + NumericDocValues singleton = DocValues.unwrapSingleton(docValues); + if (singleton != null) { + return singletonReader(singleton); + } + return sortedReader(docValues); + } + NumericDocValues singleton = context.reader().getNumericDocValues(fieldName); + if (singleton != null) { + return singletonReader(singleton); + } + return new ConstantNullsReader(); + } + + protected abstract AllReader singletonReader(NumericDocValues docValues); + + protected abstract AllReader sortedReader(SortedNumericDocValues docValues); + + public static class Singleton extends BlockDocValuesReader implements BlockDocValuesReader.NumericDocValuesAccessor { + final NumericDocValues numericDocValues; + + Singleton(NumericDocValues numericDocValues) { + this.numericDocValues = numericDocValues; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + if (numericDocValues instanceof OptionalColumnAtATimeReader direct) { + Block result = direct.tryRead(factory, docs, offset, nullsFiltered, null, false); + if (result != null) { + return result; + } + } + try (LongBuilder builder = factory.longsFromDocValues(docs.count() - offset)) { + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + if (numericDocValues.advanceExact(doc)) { + builder.appendLong(numericDocValues.longValue()); + } else { + builder.appendNull(); + } + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + LongBuilder blockBuilder = (LongBuilder) builder; + if (numericDocValues.advanceExact(docId)) { + blockBuilder.appendLong(numericDocValues.longValue()); + } else { + blockBuilder.appendNull(); + } + } + + @Override + public int docId() { + return numericDocValues.docID(); + } + + @Override + public String toString() { + return "LongsFromDocValues.Singleton"; + } + + @Override + public NumericDocValues numericDocValues() { + return numericDocValues; + } + } + + public static class Sorted extends BlockDocValuesReader { + private final SortedNumericDocValues numericDocValues; + + Sorted(SortedNumericDocValues numericDocValues) { + this.numericDocValues = numericDocValues; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + try (LongBuilder builder = factory.longsFromDocValues(docs.count() - offset)) { + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + read(doc, builder); + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + read(docId, (LongBuilder) builder); + } + + private void read(int doc, LongBuilder builder) throws IOException { + if (false == numericDocValues.advanceExact(doc)) { + builder.appendNull(); + return; + } + int count = numericDocValues.docValueCount(); + if (count == 1) { + builder.appendLong(numericDocValues.nextValue()); + return; + } + builder.beginPositionEntry(); + for (int v = 0; v < count; v++) { + builder.appendLong(numericDocValues.nextValue()); + } + builder.endPositionEntry(); + } + + @Override + public int docId() { + return numericDocValues.docID(); + } + + @Override + public String toString() { + return "LongsFromDocValues.Sorted"; + } + } +} diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/DoublesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/DoublesBlockLoader.java index 7e6a700f156ba..abebc6447b4d2 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/DoublesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/DoublesBlockLoader.java @@ -9,151 +9,26 @@ package org.elasticsearch.index.mapper.blockloader.docvalues; -import org.apache.lucene.index.DocValues; -import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.NumericDocValues; import org.apache.lucene.index.SortedNumericDocValues; -import org.elasticsearch.index.mapper.BlockLoader; - -import java.io.IOException; - -public class DoublesBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { - private final String fieldName; - private final BlockDocValuesReader.ToDouble toDouble; +public class DoublesBlockLoader extends AbstractDoublesFromDocValuesBlockLoader { public DoublesBlockLoader(String fieldName, BlockDocValuesReader.ToDouble toDouble) { - this.fieldName = fieldName; - this.toDouble = toDouble; + super(fieldName, toDouble); } @Override - public Builder builder(BlockFactory factory, int expectedCount) { - return factory.doubles(expectedCount); + protected AllReader singletonReader(NumericDocValues docValues, BlockDocValuesReader.ToDouble toDouble) { + return new Singleton(docValues, toDouble); } @Override - public AllReader reader(LeafReaderContext context) throws IOException { - SortedNumericDocValues docValues = context.reader().getSortedNumericDocValues(fieldName); - if (docValues != null) { - NumericDocValues singleton = DocValues.unwrapSingleton(docValues); - if (singleton != null) { - return new SingletonDoubles(singleton, toDouble); - } - return new Doubles(docValues, toDouble); - } - NumericDocValues singleton = context.reader().getNumericDocValues(fieldName); - if (singleton != null) { - return new SingletonDoubles(singleton, toDouble); - } - return new ConstantNullsReader(); + protected AllReader sortedReader(SortedNumericDocValues docValues, BlockDocValuesReader.ToDouble toDouble) { + return new Sorted(docValues, toDouble); } - public static class SingletonDoubles extends BlockDocValuesReader implements BlockDocValuesReader.NumericDocValuesAccessor { - private final NumericDocValues docValues; - private final ToDouble toDouble; - - SingletonDoubles(NumericDocValues docValues, ToDouble toDouble) { - this.docValues = docValues; - this.toDouble = toDouble; - } - - @Override - public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { - if (docValues instanceof BlockLoader.OptionalColumnAtATimeReader direct) { - BlockLoader.Block result = direct.tryRead(factory, docs, offset, nullsFiltered, toDouble, false); - if (result != null) { - return result; - } - } - try (BlockLoader.DoubleBuilder builder = factory.doublesFromDocValues(docs.count() - offset)) { - for (int i = offset; i < docs.count(); i++) { - int doc = docs.get(i); - if (docValues.advanceExact(doc)) { - builder.appendDouble(toDouble.convert(docValues.longValue())); - } else { - builder.appendNull(); - } - } - return builder.build(); - } - } - - @Override - public void read(int docId, BlockLoader.StoredFields storedFields, Builder builder) throws IOException { - DoubleBuilder blockBuilder = (DoubleBuilder) builder; - if (docValues.advanceExact(docId)) { - blockBuilder.appendDouble(toDouble.convert(docValues.longValue())); - } else { - blockBuilder.appendNull(); - } - } - - @Override - public int docId() { - return docValues.docID(); - } - - @Override - public String toString() { - return "BlockDocValuesReader.SingletonDoubles"; - } - - @Override - public NumericDocValues numericDocValues() { - return docValues; - } - } - - public static class Doubles extends BlockDocValuesReader { - private final SortedNumericDocValues docValues; - private final ToDouble toDouble; - - Doubles(SortedNumericDocValues docValues, ToDouble toDouble) { - this.docValues = docValues; - this.toDouble = toDouble; - } - - @Override - public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { - try (BlockLoader.DoubleBuilder builder = factory.doublesFromDocValues(docs.count() - offset)) { - for (int i = offset; i < docs.count(); i++) { - int doc = docs.get(i); - read(doc, builder); - } - return builder.build(); - } - } - - @Override - public void read(int docId, BlockLoader.StoredFields storedFields, Builder builder) throws IOException { - read(docId, (DoubleBuilder) builder); - } - - private void read(int doc, DoubleBuilder builder) throws IOException { - if (false == docValues.advanceExact(doc)) { - builder.appendNull(); - return; - } - int count = docValues.docValueCount(); - if (count == 1) { - builder.appendDouble(toDouble.convert(docValues.nextValue())); - return; - } - builder.beginPositionEntry(); - for (int v = 0; v < count; v++) { - builder.appendDouble(toDouble.convert(docValues.nextValue())); - } - builder.endPositionEntry(); - } - - @Override - public int docId() { - return docValues.docID(); - } - - @Override - public String toString() { - return "BlockDocValuesReader.Doubles"; - } + @Override + public String toString() { + return "DoublesFromDocValues[" + fieldName + "]"; } } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/LongsBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/LongsBlockLoader.java index 16425fb8a7ead..d10fbdefe0ab9 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/LongsBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/LongsBlockLoader.java @@ -9,145 +9,26 @@ package org.elasticsearch.index.mapper.blockloader.docvalues; -import org.apache.lucene.index.DocValues; -import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.NumericDocValues; import org.apache.lucene.index.SortedNumericDocValues; -import org.elasticsearch.index.mapper.BlockLoader; - -import java.io.IOException; - -public class LongsBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { - private final String fieldName; +public class LongsBlockLoader extends AbstractLongsFromDocValuesBlockLoader { public LongsBlockLoader(String fieldName) { - this.fieldName = fieldName; + super(fieldName); } @Override - public Builder builder(BlockFactory factory, int expectedCount) { - return factory.longs(expectedCount); + protected AllReader singletonReader(NumericDocValues docValues) { + return new Singleton(docValues); } @Override - public AllReader reader(LeafReaderContext context) throws IOException { - SortedNumericDocValues docValues = context.reader().getSortedNumericDocValues(fieldName); - if (docValues != null) { - NumericDocValues singleton = DocValues.unwrapSingleton(docValues); - if (singleton != null) { - return new SingletonLongs(singleton); - } - return new Longs(docValues); - } - NumericDocValues singleton = context.reader().getNumericDocValues(fieldName); - if (singleton != null) { - return new SingletonLongs(singleton); - } - return new ConstantNullsReader(); + protected AllReader sortedReader(SortedNumericDocValues docValues) { + return new Sorted(docValues); } - public static class SingletonLongs extends BlockDocValuesReader implements BlockDocValuesReader.NumericDocValuesAccessor { - final NumericDocValues numericDocValues; - - SingletonLongs(NumericDocValues numericDocValues) { - this.numericDocValues = numericDocValues; - } - - @Override - public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { - if (numericDocValues instanceof BlockLoader.OptionalColumnAtATimeReader direct) { - BlockLoader.Block result = direct.tryRead(factory, docs, offset, nullsFiltered, null, false); - if (result != null) { - return result; - } - } - try (BlockLoader.LongBuilder builder = factory.longsFromDocValues(docs.count() - offset)) { - for (int i = offset; i < docs.count(); i++) { - int doc = docs.get(i); - if (numericDocValues.advanceExact(doc)) { - builder.appendLong(numericDocValues.longValue()); - } else { - builder.appendNull(); - } - } - return builder.build(); - } - } - - @Override - public void read(int docId, BlockLoader.StoredFields storedFields, Builder builder) throws IOException { - BlockLoader.LongBuilder blockBuilder = (BlockLoader.LongBuilder) builder; - if (numericDocValues.advanceExact(docId)) { - blockBuilder.appendLong(numericDocValues.longValue()); - } else { - blockBuilder.appendNull(); - } - } - - @Override - public int docId() { - return numericDocValues.docID(); - } - - @Override - public String toString() { - return "BlockDocValuesReader.SingletonLongs"; - } - - @Override - public NumericDocValues numericDocValues() { - return numericDocValues; - } - } - - public static class Longs extends BlockDocValuesReader { - private final SortedNumericDocValues numericDocValues; - - Longs(SortedNumericDocValues numericDocValues) { - this.numericDocValues = numericDocValues; - } - - @Override - public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { - try (BlockLoader.LongBuilder builder = factory.longsFromDocValues(docs.count() - offset)) { - for (int i = offset; i < docs.count(); i++) { - int doc = docs.get(i); - read(doc, builder); - } - return builder.build(); - } - } - - @Override - public void read(int docId, BlockLoader.StoredFields storedFields, Builder builder) throws IOException { - read(docId, (LongBuilder) builder); - } - - private void read(int doc, LongBuilder builder) throws IOException { - if (false == numericDocValues.advanceExact(doc)) { - builder.appendNull(); - return; - } - int count = numericDocValues.docValueCount(); - if (count == 1) { - builder.appendLong(numericDocValues.nextValue()); - return; - } - builder.beginPositionEntry(); - for (int v = 0; v < count; v++) { - builder.appendLong(numericDocValues.nextValue()); - } - builder.endPositionEntry(); - } - - @Override - public int docId() { - return numericDocValues.docID(); - } - - @Override - public String toString() { - return "BlockDocValuesReader.Longs"; - } + @Override + public String toString() { + return "LongsFromDocValues[" + fieldName + "]"; } } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java index f3e2633717a4b..0a52eaec023b5 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/DateFieldMapperTests.java @@ -855,7 +855,7 @@ public void testSingletonLongBulkBlockReadingManyValues() throws Exception { LeafReaderContext context = reader.leaves().get(0); { // One big doc block - var columnReader = (LongsBlockLoader.SingletonLongs) blockLoader.columnAtATimeReader(context); + var columnReader = (LongsBlockLoader.Singleton) blockLoader.columnAtATimeReader(context); assertThat(columnReader.numericDocValues(), instanceOf(BlockLoader.OptionalColumnAtATimeReader.class)); var docBlock = TestBlock.docs(IntStream.range(from, to).toArray()); var block = (TestBlock) columnReader.read(TestBlock.factory(), docBlock, 0, false); @@ -867,7 +867,7 @@ public void testSingletonLongBulkBlockReadingManyValues() throws Exception { { // Smaller doc blocks int docBlockSize = 1000; - var columnReader = (LongsBlockLoader.SingletonLongs) blockLoader.columnAtATimeReader(context); + var columnReader = (LongsBlockLoader.Singleton) blockLoader.columnAtATimeReader(context); assertThat(columnReader.numericDocValues(), instanceOf(BlockLoader.OptionalColumnAtATimeReader.class)); for (int i = from; i < to; i += docBlockSize) { var docBlock = TestBlock.docs(IntStream.range(i, i + docBlockSize).toArray()); @@ -881,7 +881,7 @@ public void testSingletonLongBulkBlockReadingManyValues() throws Exception { } { // One smaller doc block: - var columnReader = (LongsBlockLoader.SingletonLongs) blockLoader.columnAtATimeReader(context); + var columnReader = (LongsBlockLoader.Singleton) blockLoader.columnAtATimeReader(context); assertThat(columnReader.numericDocValues(), instanceOf(BlockLoader.OptionalColumnAtATimeReader.class)); var docBlock = TestBlock.docs(IntStream.range(1010, 2020).toArray()); var block = (TestBlock) columnReader.read(TestBlock.factory(), docBlock, 0, false); @@ -893,7 +893,7 @@ public void testSingletonLongBulkBlockReadingManyValues() throws Exception { } { // Read two tiny blocks: - var columnReader = (LongsBlockLoader.SingletonLongs) blockLoader.columnAtATimeReader(context); + var columnReader = (LongsBlockLoader.Singleton) blockLoader.columnAtATimeReader(context); assertThat(columnReader.numericDocValues(), instanceOf(BlockLoader.OptionalColumnAtATimeReader.class)); var docBlock = TestBlock.docs(IntStream.range(32, 64).toArray()); var block = (TestBlock) columnReader.read(TestBlock.factory(), docBlock, 0, false); diff --git a/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperTestCase.java b/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperTestCase.java index 6183e23d6aff3..cfd7346329c52 100644 --- a/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/index/mapper/MapperTestCase.java @@ -1534,12 +1534,12 @@ public void testSingletonIntBulkBlockReading() throws IOException { public void testSingletonLongBulkBlockReading() throws IOException { assumeTrue("field type supports bulk singleton long reading", supportsBulkLongBlockReading()); - testSingletonBulkBlockReading(columnAtATimeReader -> (LongsBlockLoader.SingletonLongs) columnAtATimeReader); + testSingletonBulkBlockReading(columnAtATimeReader -> (LongsBlockLoader.Singleton) columnAtATimeReader); } public void testSingletonDoubleBulkBlockReading() throws IOException { assumeTrue("field type supports bulk singleton double reading", supportsBulkDoubleBlockReading()); - testSingletonBulkBlockReading(columnAtATimeReader -> (DoublesBlockLoader.SingletonDoubles) columnAtATimeReader); + testSingletonBulkBlockReading(columnAtATimeReader -> (DoublesBlockLoader.Singleton) columnAtATimeReader); } private void testSingletonBulkBlockReading(Function readerCast) @@ -1643,8 +1643,8 @@ private void testSingletonBulkBlockReading(Function "BytesRefsFromOrds.Singleton"; - case "Ints" -> "IntsFromDocValues.Singleton"; - default -> "BlockDocValuesReader.Singleton" + type; + default -> type + "FromDocValues.Singleton"; }; } static String multiName(String type) { return switch (type) { case "Ordinals" -> "BytesRefsFromOrds.SortedSet"; - case "Ints" -> "IntsFromDocValues.Sorted"; - default -> "BlockDocValuesReader." + type; + default -> type + "FromDocValues.Sorted"; }; } From 9cf645bb460776f68d9745f6bf3ad10c3da1b412 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Mon, 10 Nov 2025 07:52:36 -0500 Subject: [PATCH 2/6] Finish remaining MV_MIN and MV_MAX --- .../{ => fn}/MvMaxBytesRefsFromOrdsBlockLoader.java | 0 .../{ => fn}/MvMaxIntsFromDocValuesBlockLoader.java | 11 +++-------- .../{ => fn}/MvMinBytesRefsFromOrdsBlockLoader.java | 0 .../{ => fn}/MvMinIntsFromDocValuesBlockLoader.java | 0 .../{ => fn}/Utf8CodePointsFromOrdsBlockLoader.java | 0 .../{ => fn}/AbstractFromOrdsBlockLoaderTests.java | 2 +- .../AbstractIntsFromDocValuesBlockLoaderTests.java | 4 ++-- .../docvalues/{ => fn}/ForceDocAtATime.java | 0 .../blockloader/docvalues/{ => fn}/MockWarnings.java | 0 .../MvMaxBytesRefsFromOrdsBlockLoaderTests.java | 1 + .../MvMaxIntsFromDocValuesBlockLoaderTests.java | 1 + .../MvMinBytesRefsFromOrdsBlockLoaderTests.java | 1 + .../MvMinIntsFromDocValuesBlockLoaderTests.java | 1 + .../Utf8CodePointsFromOrdsBlockLoaderTests.java | 1 + 14 files changed, 11 insertions(+), 11 deletions(-) rename server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/MvMaxBytesRefsFromOrdsBlockLoader.java (100%) rename server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/MvMaxIntsFromDocValuesBlockLoader.java (90%) rename server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/MvMinBytesRefsFromOrdsBlockLoader.java (100%) rename server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/MvMinIntsFromDocValuesBlockLoader.java (100%) rename server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/Utf8CodePointsFromOrdsBlockLoader.java (100%) rename server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/AbstractFromOrdsBlockLoaderTests.java (98%) rename server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/AbstractIntsFromDocValuesBlockLoaderTests.java (96%) rename server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/ForceDocAtATime.java (100%) rename server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/MockWarnings.java (100%) rename server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/MvMaxBytesRefsFromOrdsBlockLoaderTests.java (97%) rename server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/MvMaxIntsFromDocValuesBlockLoaderTests.java (97%) rename server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/MvMinBytesRefsFromOrdsBlockLoaderTests.java (97%) rename server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/MvMinIntsFromDocValuesBlockLoaderTests.java (97%) rename server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/{ => fn}/Utf8CodePointsFromOrdsBlockLoaderTests.java (97%) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMaxBytesRefsFromOrdsBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoader.java similarity index 100% rename from server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMaxBytesRefsFromOrdsBlockLoader.java rename to server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoader.java diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMaxIntsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoader.java similarity index 90% rename from server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMaxIntsFromDocValuesBlockLoader.java rename to server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoader.java index ed1571419effd..850cf84587baf 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMaxIntsFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoader.java @@ -14,6 +14,8 @@ import java.io.IOException; +import static org.elasticsearch.index.mapper.blockloader.docvalues.MvMaxLongsFromDocValuesBlockLoader.MvMaxSorted.discardAllButLast; + /** * Loads the MAX {@code int} in each doc. */ @@ -65,7 +67,7 @@ private void read(int doc, IntBuilder builder) throws IOException { builder.appendNull(); return; } - discardAllButLast(); + discardAllButLast(numericDocValues); builder.appendInt(Math.toIntExact(numericDocValues.nextValue())); } @@ -74,13 +76,6 @@ public int docId() { return numericDocValues.docID(); } - private void discardAllButLast() throws IOException { - int count = numericDocValues.docValueCount(); - for (int i = 0; i < count - 1; i++) { - numericDocValues.nextValue(); - } - } - @Override public String toString() { return "MvMaxIntsFromDocValues.Sorted"; diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMinBytesRefsFromOrdsBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoader.java similarity index 100% rename from server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMinBytesRefsFromOrdsBlockLoader.java rename to server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoader.java diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMinIntsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoader.java similarity index 100% rename from server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMinIntsFromDocValuesBlockLoader.java rename to server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoader.java diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/Utf8CodePointsFromOrdsBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoader.java similarity index 100% rename from server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/Utf8CodePointsFromOrdsBlockLoader.java rename to server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoader.java diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractFromOrdsBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractFromOrdsBlockLoaderTests.java similarity index 98% rename from server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractFromOrdsBlockLoaderTests.java rename to server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractFromOrdsBlockLoaderTests.java index 09a9079dd2023..78e8b42e376bb 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractFromOrdsBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractFromOrdsBlockLoaderTests.java @@ -26,7 +26,7 @@ import java.util.ArrayList; import java.util.List; -import static org.elasticsearch.index.mapper.blockloader.docvalues.Utf8CodePointsFromOrdsBlockLoader.LOW_CARDINALITY; +import static org.elasticsearch.index.mapper.blockloader.docvalues.fn.Utf8CodePointsFromOrdsBlockLoader.LOW_CARDINALITY; public abstract class AbstractFromOrdsBlockLoaderTests extends ESTestCase { @ParametersFactory(argumentFormatting = "blockAtATime=%s, lowCardinality=%s, multiValues=%s, missingValues=%s") diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractIntsFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractIntsFromDocValuesBlockLoaderTests.java similarity index 96% rename from server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractIntsFromDocValuesBlockLoaderTests.java rename to server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractIntsFromDocValuesBlockLoaderTests.java index 9bf41c8692572..fbd9efb4f2110 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractIntsFromDocValuesBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractIntsFromDocValuesBlockLoaderTests.java @@ -85,7 +85,7 @@ protected final TestBlock read(BlockLoader loader, BlockLoader.AllReader reader, return (TestBlock) toUse.read(TestBlock.factory(), docs, 0, false); } - private static IntField field(int codePointCount) { - return new IntField("field", codePointCount, Field.Store.NO); + private static IntField field(int v) { + return new IntField("field", v, Field.Store.NO); } } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/ForceDocAtATime.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/ForceDocAtATime.java similarity index 100% rename from server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/ForceDocAtATime.java rename to server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/ForceDocAtATime.java diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MockWarnings.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MockWarnings.java similarity index 100% rename from server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MockWarnings.java rename to server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MockWarnings.java diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMaxBytesRefsFromOrdsBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoaderTests.java similarity index 97% rename from server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMaxBytesRefsFromOrdsBlockLoaderTests.java rename to server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoaderTests.java index 7b4e3772f3bd5..99adec4373187 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMaxBytesRefsFromOrdsBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoaderTests.java @@ -13,6 +13,7 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxBytesRefsFromOrdsBlockLoader; import org.hamcrest.Matcher; import java.io.IOException; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMaxIntsFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoaderTests.java similarity index 97% rename from server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMaxIntsFromDocValuesBlockLoaderTests.java rename to server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoaderTests.java index f60431ecbdafd..83ffc5007afd2 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMaxIntsFromDocValuesBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoaderTests.java @@ -12,6 +12,7 @@ import org.apache.lucene.index.LeafReaderContext; import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxIntsFromDocValuesBlockLoader; import org.hamcrest.Matcher; import java.io.IOException; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMinBytesRefsFromOrdsBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoaderTests.java similarity index 97% rename from server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMinBytesRefsFromOrdsBlockLoaderTests.java rename to server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoaderTests.java index 468bbdfa384c7..2515c6c4155fa 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMinBytesRefsFromOrdsBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoaderTests.java @@ -13,6 +13,7 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMinBytesRefsFromOrdsBlockLoader; import org.hamcrest.Matcher; import java.io.IOException; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMinIntsFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoaderTests.java similarity index 97% rename from server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMinIntsFromDocValuesBlockLoaderTests.java rename to server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoaderTests.java index c32010366448a..7a7c947a826db 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/MvMinIntsFromDocValuesBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoaderTests.java @@ -12,6 +12,7 @@ import org.apache.lucene.index.LeafReaderContext; import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMinIntsFromDocValuesBlockLoader; import org.hamcrest.Matcher; import java.io.IOException; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/Utf8CodePointsFromOrdsBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java similarity index 97% rename from server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/Utf8CodePointsFromOrdsBlockLoaderTests.java rename to server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java index dac645d4c7557..f65fed1e3a7ab 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/Utf8CodePointsFromOrdsBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java @@ -14,6 +14,7 @@ import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.index.mapper.KeywordFieldMapper; import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.index.mapper.blockloader.docvalues.fn.Utf8CodePointsFromOrdsBlockLoader; import org.hamcrest.Matcher; import java.io.IOException; From 5c8953ddf71c33c9b297bdd9a7094ca1d90ad5c6 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Mon, 10 Nov 2025 07:56:31 -0500 Subject: [PATCH 3/6] fmt --- server/src/main/java/module-info.java | 1 + .../AbstractBooleansBlockLoader.java | 150 ++++++++++++++++++ .../AbstractBytesRefsFromOrdsBlockLoader.java | 6 +- ...stractDoublesFromDocValuesBlockLoader.java | 4 +- .../AbstractIntsFromDocValuesBlockLoader.java | 4 +- ...AbstractLongsFromDocValuesBlockLoader.java | 2 +- .../docvalues/BooleansBlockLoader.java | 131 ++------------- .../blockloader/docvalues/Warnings.java | 2 +- .../fn/MvMaxBooleansBlockLoader.java | 83 ++++++++++ .../fn/MvMaxBytesRefsFromOrdsBlockLoader.java | 4 +- .../MvMaxDoublesFromDocValuesBlockLoader.java | 88 ++++++++++ .../fn/MvMaxIntsFromDocValuesBlockLoader.java | 6 +- .../MvMaxLongsFromDocValuesBlockLoader.java | 91 +++++++++++ .../fn/MvMinBooleansBlockLoader.java | 80 ++++++++++ .../fn/MvMinBytesRefsFromOrdsBlockLoader.java | 4 +- .../MvMinDoublesFromDocValuesBlockLoader.java | 85 ++++++++++ .../fn/MvMinIntsFromDocValuesBlockLoader.java | 4 +- .../MvMinLongsFromDocValuesBlockLoader.java | 83 ++++++++++ .../fn/Utf8CodePointsFromOrdsBlockLoader.java | 4 +- ...BooleansFromDocValuesBlockLoaderTests.java | 90 +++++++++++ ...tDoublesFromDocValuesBlockLoaderTests.java | 91 +++++++++++ .../fn/AbstractFromOrdsBlockLoaderTests.java | 2 +- ...ractIntsFromDocValuesBlockLoaderTests.java | 2 +- ...actLongsFromDocValuesBlockLoaderTests.java | 91 +++++++++++ .../docvalues/fn/ForceDocAtATime.java | 2 +- .../docvalues/fn/MockWarnings.java | 4 +- ...BooleansFromDocValuesBlockLoaderTests.java | 81 ++++++++++ ...vMaxBytesRefsFromOrdsBlockLoaderTests.java | 4 +- ...xDoublesFromDocValuesBlockLoaderTests.java | 82 ++++++++++ ...vMaxIntsFromDocValuesBlockLoaderTests.java | 4 +- ...MaxLongsFromDocValuesBlockLoaderTests.java | 82 ++++++++++ ...BooleansFromDocValuesBlockLoaderTests.java | 81 ++++++++++ ...vMinBytesRefsFromOrdsBlockLoaderTests.java | 4 +- ...nDoublesFromDocValuesBlockLoaderTests.java | 82 ++++++++++ ...vMinIntsFromDocValuesBlockLoaderTests.java | 4 +- ...MinLongsFromDocValuesBlockLoaderTests.java | 82 ++++++++++ ...tf8CodePointsFromOrdsBlockLoaderTests.java | 4 +- .../xpack/esql/action/TimeSeriesIT.java | 5 +- 38 files changed, 1474 insertions(+), 155 deletions(-) create mode 100644 server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBooleansBlockLoader.java create mode 100644 server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java create mode 100644 server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoader.java create mode 100644 server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoader.java create mode 100644 server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansBlockLoader.java create mode 100644 server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoader.java create mode 100644 server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoader.java create mode 100644 server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractBooleansFromDocValuesBlockLoaderTests.java create mode 100644 server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractDoublesFromDocValuesBlockLoaderTests.java create mode 100644 server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractLongsFromDocValuesBlockLoaderTests.java create mode 100644 server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansFromDocValuesBlockLoaderTests.java create mode 100644 server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoaderTests.java create mode 100644 server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoaderTests.java create mode 100644 server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansFromDocValuesBlockLoaderTests.java create mode 100644 server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoaderTests.java create mode 100644 server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoaderTests.java diff --git a/server/src/main/java/module-info.java b/server/src/main/java/module-info.java index 6a4d447c8067d..10955caacf6b4 100644 --- a/server/src/main/java/module-info.java +++ b/server/src/main/java/module-info.java @@ -501,4 +501,5 @@ exports org.elasticsearch.index.codec.vectors.es93 to org.elasticsearch.test.knn; exports org.elasticsearch.search.crossproject; exports org.elasticsearch.index.mapper.blockloader.docvalues; + exports org.elasticsearch.index.mapper.blockloader.docvalues.fn; } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBooleansBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBooleansBlockLoader.java new file mode 100644 index 0000000000000..65287b2425925 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBooleansBlockLoader.java @@ -0,0 +1,150 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues; + +import org.apache.lucene.index.DocValues; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.SortedNumericDocValues; + +import java.io.IOException; + +public abstract class AbstractBooleansBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { + protected final String fieldName; + + public AbstractBooleansBlockLoader(String fieldName) { + this.fieldName = fieldName; + } + + @Override + public final BooleanBuilder builder(BlockFactory factory, int expectedCount) { + return factory.booleans(expectedCount); + } + + @Override + public AllReader reader(LeafReaderContext context) throws IOException { + SortedNumericDocValues docValues = context.reader().getSortedNumericDocValues(fieldName); + if (docValues != null) { + NumericDocValues singleton = DocValues.unwrapSingleton(docValues); + if (singleton != null) { + return singletonReader(singleton); + } + return sortedReader(docValues); + } + NumericDocValues singleton = context.reader().getNumericDocValues(fieldName); + if (singleton != null) { + return singletonReader(singleton); + } + return new ConstantNullsReader(); + } + + protected abstract AllReader singletonReader(NumericDocValues docValues); + + protected abstract AllReader sortedReader(SortedNumericDocValues docValues); + + public static class Singleton extends BlockDocValuesReader { + private final NumericDocValues numericDocValues; + + public Singleton(NumericDocValues numericDocValues) { + this.numericDocValues = numericDocValues; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + try (BooleanBuilder builder = factory.booleansFromDocValues(docs.count() - offset)) { + int lastDoc = -1; + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + if (doc < lastDoc) { + throw new IllegalStateException("docs within same block must be in order"); + } + if (numericDocValues.advanceExact(doc)) { + builder.appendBoolean(numericDocValues.longValue() != 0); + } else { + builder.appendNull(); + } + lastDoc = doc; + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + BooleanBuilder blockBuilder = (BooleanBuilder) builder; + if (numericDocValues.advanceExact(docId)) { + blockBuilder.appendBoolean(numericDocValues.longValue() != 0); + } else { + blockBuilder.appendNull(); + } + } + + @Override + public int docId() { + return numericDocValues.docID(); + } + + @Override + public String toString() { + return "BooleansFromDocValues.Singleton"; + } + } + + static class Sorted extends BlockDocValuesReader { + private final SortedNumericDocValues numericDocValues; + + Sorted(SortedNumericDocValues numericDocValues) { + this.numericDocValues = numericDocValues; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + try (BooleanBuilder builder = factory.booleansFromDocValues(docs.count() - offset)) { + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + read(doc, builder); + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + read(docId, (BooleanBuilder) builder); + } + + private void read(int doc, BooleanBuilder builder) throws IOException { + if (false == numericDocValues.advanceExact(doc)) { + builder.appendNull(); + return; + } + int count = numericDocValues.docValueCount(); + if (count == 1) { + builder.appendBoolean(numericDocValues.nextValue() != 0); + return; + } + builder.beginPositionEntry(); + for (int v = 0; v < count; v++) { + builder.appendBoolean(numericDocValues.nextValue() != 0); + } + builder.endPositionEntry(); + } + + @Override + public int docId() { + return numericDocValues.docID(); + } + + @Override + public String toString() { + return "BooleansFromDocValues.Sorted"; + } + } +} diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBytesRefsFromOrdsBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBytesRefsFromOrdsBlockLoader.java index bee53465ed100..824d9e30e33ba 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBytesRefsFromOrdsBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBytesRefsFromOrdsBlockLoader.java @@ -20,10 +20,10 @@ /** * Loads {@code keyword} style fields that are stored as a lookup table. */ -abstract class AbstractBytesRefsFromOrdsBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { +public abstract class AbstractBytesRefsFromOrdsBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { protected final String fieldName; - AbstractBytesRefsFromOrdsBlockLoader(String fieldName) { + public AbstractBytesRefsFromOrdsBlockLoader(String fieldName) { this.fieldName = fieldName; } @@ -56,7 +56,7 @@ public final AllReader reader(LeafReaderContext context) throws IOException { protected static class Singleton extends BlockDocValuesReader { private final SortedDocValues ordinals; - Singleton(SortedDocValues ordinals) { + public Singleton(SortedDocValues ordinals) { this.ordinals = ordinals; } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractDoublesFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractDoublesFromDocValuesBlockLoader.java index 39a8727a8df8f..0d5426cb39e9f 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractDoublesFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractDoublesFromDocValuesBlockLoader.java @@ -58,7 +58,7 @@ public static class Singleton extends BlockDocValuesReader implements BlockDocVa private final NumericDocValues docValues; private final ToDouble toDouble; - Singleton(NumericDocValues docValues, ToDouble toDouble) { + public Singleton(NumericDocValues docValues, ToDouble toDouble) { this.docValues = docValues; this.toDouble = toDouble; } @@ -159,7 +159,7 @@ public int docId() { @Override public String toString() { - return "LongsFromDocValues.Sorted"; + return "DoublesFromDocValues.Sorted"; } } } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractIntsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractIntsFromDocValuesBlockLoader.java index 22b2ce7162d64..c01c115208dc1 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractIntsFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractIntsFromDocValuesBlockLoader.java @@ -22,7 +22,7 @@ public abstract class AbstractIntsFromDocValuesBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { protected final String fieldName; - AbstractIntsFromDocValuesBlockLoader(String fieldName) { + protected AbstractIntsFromDocValuesBlockLoader(String fieldName) { this.fieldName = fieldName; } @@ -55,7 +55,7 @@ public final AllReader reader(LeafReaderContext context) throws IOException { public static class Singleton extends BlockDocValuesReader implements BlockDocValuesReader.NumericDocValuesAccessor { private final NumericDocValues numericDocValues; - Singleton(NumericDocValues numericDocValues) { + public Singleton(NumericDocValues numericDocValues) { this.numericDocValues = numericDocValues; } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractLongsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractLongsFromDocValuesBlockLoader.java index c4d981329f6bd..834e6c8a5fabd 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractLongsFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractLongsFromDocValuesBlockLoader.java @@ -55,7 +55,7 @@ public final AllReader reader(LeafReaderContext context) throws IOException { public static class Singleton extends BlockDocValuesReader implements BlockDocValuesReader.NumericDocValuesAccessor { final NumericDocValues numericDocValues; - Singleton(NumericDocValues numericDocValues) { + public Singleton(NumericDocValues numericDocValues) { this.numericDocValues = numericDocValues; } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/BooleansBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/BooleansBlockLoader.java index c82a91ccb9dd7..0a1cf0ae048a6 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/BooleansBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/BooleansBlockLoader.java @@ -9,139 +9,26 @@ package org.elasticsearch.index.mapper.blockloader.docvalues; -import org.apache.lucene.index.DocValues; -import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.NumericDocValues; import org.apache.lucene.index.SortedNumericDocValues; -import org.elasticsearch.index.mapper.BlockLoader; - -import java.io.IOException; - -public class BooleansBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { - private final String fieldName; +public class BooleansBlockLoader extends AbstractBooleansBlockLoader { public BooleansBlockLoader(String fieldName) { - this.fieldName = fieldName; + super(fieldName); } @Override - public BooleanBuilder builder(BlockFactory factory, int expectedCount) { - return factory.booleans(expectedCount); + protected AllReader singletonReader(NumericDocValues docValues) { + return new Singleton(docValues); } @Override - public AllReader reader(LeafReaderContext context) throws IOException { - SortedNumericDocValues docValues = context.reader().getSortedNumericDocValues(fieldName); - if (docValues != null) { - NumericDocValues singleton = DocValues.unwrapSingleton(docValues); - if (singleton != null) { - return new SingletonBooleans(singleton); - } - return new Booleans(docValues); - } - NumericDocValues singleton = context.reader().getNumericDocValues(fieldName); - if (singleton != null) { - return new SingletonBooleans(singleton); - } - return new ConstantNullsReader(); - } - - private static class SingletonBooleans extends BlockDocValuesReader { - private final NumericDocValues numericDocValues; - - SingletonBooleans(NumericDocValues numericDocValues) { - this.numericDocValues = numericDocValues; - } - - @Override - public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { - try (BlockLoader.BooleanBuilder builder = factory.booleansFromDocValues(docs.count() - offset)) { - int lastDoc = -1; - for (int i = offset; i < docs.count(); i++) { - int doc = docs.get(i); - if (doc < lastDoc) { - throw new IllegalStateException("docs within same block must be in order"); - } - if (numericDocValues.advanceExact(doc)) { - builder.appendBoolean(numericDocValues.longValue() != 0); - } else { - builder.appendNull(); - } - lastDoc = doc; - } - return builder.build(); - } - } - - @Override - public void read(int docId, BlockLoader.StoredFields storedFields, Builder builder) throws IOException { - BooleanBuilder blockBuilder = (BooleanBuilder) builder; - if (numericDocValues.advanceExact(docId)) { - blockBuilder.appendBoolean(numericDocValues.longValue() != 0); - } else { - blockBuilder.appendNull(); - } - } - - @Override - public int docId() { - return numericDocValues.docID(); - } - - @Override - public String toString() { - return "BlockDocValuesReader.SingletonBooleans"; - } + protected AllReader sortedReader(SortedNumericDocValues docValues) { + return new Sorted(docValues); } - private static class Booleans extends BlockDocValuesReader { - private final SortedNumericDocValues numericDocValues; - - Booleans(SortedNumericDocValues numericDocValues) { - this.numericDocValues = numericDocValues; - } - - @Override - public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { - try (BlockLoader.BooleanBuilder builder = factory.booleansFromDocValues(docs.count() - offset)) { - for (int i = offset; i < docs.count(); i++) { - int doc = docs.get(i); - read(doc, builder); - } - return builder.build(); - } - } - - @Override - public void read(int docId, BlockLoader.StoredFields storedFields, Builder builder) throws IOException { - read(docId, (BooleanBuilder) builder); - } - - private void read(int doc, BooleanBuilder builder) throws IOException { - if (false == numericDocValues.advanceExact(doc)) { - builder.appendNull(); - return; - } - int count = numericDocValues.docValueCount(); - if (count == 1) { - builder.appendBoolean(numericDocValues.nextValue() != 0); - return; - } - builder.beginPositionEntry(); - for (int v = 0; v < count; v++) { - builder.appendBoolean(numericDocValues.nextValue() != 0); - } - builder.endPositionEntry(); - } - - @Override - public int docId() { - return numericDocValues.docID(); - } - - @Override - public String toString() { - return "BlockDocValuesReader.Booleans"; - } + @Override + public String toString() { + return "BooleansFromDocValues[" + fieldName + "]"; } } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/Warnings.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/Warnings.java index 67fcb543d48c7..01282d8e4cfb6 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/Warnings.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/Warnings.java @@ -17,7 +17,7 @@ * < Warning: 299 Elasticsearch-${ver} "Line 1:27: java.lang.IllegalArgumentException: single-value function encountered multi-value" * } */ -interface Warnings { +public interface Warnings { /** * Register a warning. ESQL deduplicates and limits the number of warnings returned so it should * be fine to blast as many warnings into this as you encounter. diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java new file mode 100644 index 0000000000000..d24313d5ae829 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.SortedNumericDocValues; +import org.elasticsearch.index.mapper.blockloader.docvalues.AbstractBooleansBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; + +import java.io.IOException; + +import static org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxLongsFromDocValuesBlockLoader.MvMaxSorted.discardAllButLast; + +public class MvMaxBooleansBlockLoader extends AbstractBooleansBlockLoader { + public MvMaxBooleansBlockLoader(String fieldName) { + super(fieldName); + } + + @Override + protected AllReader singletonReader(NumericDocValues docValues) { + return new Singleton(docValues); + } + + @Override + protected AllReader sortedReader(SortedNumericDocValues docValues) { + return new MvMinSorted(docValues); + } + + @Override + public String toString() { + return "BooleansFromDocValues[" + fieldName + "]"; + } + + public static class MvMinSorted extends BlockDocValuesReader { + private final SortedNumericDocValues numericDocValues; + + MvMinSorted(SortedNumericDocValues numericDocValues) { + this.numericDocValues = numericDocValues; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + try (BooleanBuilder builder = factory.booleansFromDocValues(docs.count() - offset)) { + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + read(doc, builder); + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + read(docId, (BooleanBuilder) builder); + } + + private void read(int doc, BooleanBuilder builder) throws IOException { + if (false == numericDocValues.advanceExact(doc)) { + builder.appendNull(); + return; + } + discardAllButLast(numericDocValues); + builder.appendBoolean(numericDocValues.nextValue() != 0); + } + + @Override + public int docId() { + return numericDocValues.docID(); + } + + @Override + public String toString() { + return "MvMaxBooleansFromDocValues.Sorted"; + } + } +} diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoader.java index 4b26d784115f5..9e7604132ffe6 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoader.java @@ -7,11 +7,13 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import org.apache.lucene.index.SortedDocValues; import org.apache.lucene.index.SortedSetDocValues; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.index.mapper.blockloader.docvalues.AbstractBytesRefsFromOrdsBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; import java.io.IOException; diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoader.java new file mode 100644 index 0000000000000..28b786fc40b03 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoader.java @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.SortedNumericDocValues; +import org.elasticsearch.index.mapper.blockloader.docvalues.AbstractDoublesFromDocValuesBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; + +import java.io.IOException; + +import static org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxLongsFromDocValuesBlockLoader.MvMaxSorted.discardAllButLast; + +/** + * Loads the MAX {@code double} in each doc. + */ +public class MvMaxDoublesFromDocValuesBlockLoader extends AbstractDoublesFromDocValuesBlockLoader { + public MvMaxDoublesFromDocValuesBlockLoader(String fieldName, BlockDocValuesReader.ToDouble toDouble) { + super(fieldName, toDouble); + } + + @Override + protected AllReader singletonReader(NumericDocValues docValues, BlockDocValuesReader.ToDouble toDouble) { + return new Singleton(docValues, toDouble); + } + + @Override + protected AllReader sortedReader(SortedNumericDocValues docValues, BlockDocValuesReader.ToDouble toDouble) { + return new MvMaxSorted(docValues, toDouble); + } + + @Override + public String toString() { + return "DoublesFromDocValues[" + fieldName + "]"; + } + + public static class MvMaxSorted extends BlockDocValuesReader { + private final SortedNumericDocValues numericDocValues; + private final ToDouble toDouble; + + MvMaxSorted(SortedNumericDocValues numericDocValues, ToDouble toDouble) { + this.numericDocValues = numericDocValues; + this.toDouble = toDouble; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + try (DoubleBuilder builder = factory.doublesFromDocValues(docs.count() - offset)) { + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + read(doc, builder); + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + read(docId, (DoubleBuilder) builder); + } + + private void read(int doc, DoubleBuilder builder) throws IOException { + if (false == numericDocValues.advanceExact(doc)) { + builder.appendNull(); + return; + } + discardAllButLast(numericDocValues); + builder.appendDouble(toDouble.convert(numericDocValues.nextValue())); + } + + @Override + public int docId() { + return numericDocValues.docID(); + } + + @Override + public String toString() { + return "MvMaxDoublesFromDocValues.Sorted"; + } + } +} diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoader.java index 850cf84587baf..2a56ceb97e126 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoader.java @@ -7,14 +7,16 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import org.apache.lucene.index.NumericDocValues; import org.apache.lucene.index.SortedNumericDocValues; +import org.elasticsearch.index.mapper.blockloader.docvalues.AbstractIntsFromDocValuesBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; import java.io.IOException; -import static org.elasticsearch.index.mapper.blockloader.docvalues.MvMaxLongsFromDocValuesBlockLoader.MvMaxSorted.discardAllButLast; +import static org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxLongsFromDocValuesBlockLoader.MvMaxSorted.discardAllButLast; /** * Loads the MAX {@code int} in each doc. diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoader.java new file mode 100644 index 0000000000000..aefccd8060899 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoader.java @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.SortedNumericDocValues; +import org.elasticsearch.index.mapper.blockloader.docvalues.AbstractLongsFromDocValuesBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; + +import java.io.IOException; + +/** + * Loads the MAX {@code long} in each doc. + */ +public class MvMaxLongsFromDocValuesBlockLoader extends AbstractLongsFromDocValuesBlockLoader { + public MvMaxLongsFromDocValuesBlockLoader(String fieldName) { + super(fieldName); + } + + @Override + protected AllReader singletonReader(NumericDocValues docValues) { + return new Singleton(docValues); + } + + @Override + protected AllReader sortedReader(SortedNumericDocValues docValues) { + return new MvMaxSorted(docValues); + } + + @Override + public String toString() { + return "LongsFromDocValues[" + fieldName + "]"; + } + + public static class MvMaxSorted extends BlockDocValuesReader { + private final SortedNumericDocValues numericDocValues; + + MvMaxSorted(SortedNumericDocValues numericDocValues) { + this.numericDocValues = numericDocValues; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + try (LongBuilder builder = factory.longsFromDocValues(docs.count() - offset)) { + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + read(doc, builder); + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + read(docId, (LongBuilder) builder); + } + + private void read(int doc, LongBuilder builder) throws IOException { + if (false == numericDocValues.advanceExact(doc)) { + builder.appendNull(); + return; + } + discardAllButLast(numericDocValues); + builder.appendLong(numericDocValues.nextValue()); + } + + @Override + public int docId() { + return numericDocValues.docID(); + } + + static void discardAllButLast(SortedNumericDocValues numericDocValues) throws IOException { + int count = numericDocValues.docValueCount(); + for (int i = 0; i < count - 1; i++) { + numericDocValues.nextValue(); + } + } + + @Override + public String toString() { + return "MvMaxLongsFromDocValues.Sorted"; + } + } +} diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansBlockLoader.java new file mode 100644 index 0000000000000..dc396e6eeb3a4 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansBlockLoader.java @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.SortedNumericDocValues; +import org.elasticsearch.index.mapper.blockloader.docvalues.AbstractBooleansBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; + +import java.io.IOException; + +public class MvMinBooleansBlockLoader extends AbstractBooleansBlockLoader { + public MvMinBooleansBlockLoader(String fieldName) { + super(fieldName); + } + + @Override + protected AllReader singletonReader(NumericDocValues docValues) { + return new Singleton(docValues); + } + + @Override + protected AllReader sortedReader(SortedNumericDocValues docValues) { + return new MvMinSorted(docValues); + } + + @Override + public String toString() { + return "BooleansFromDocValues[" + fieldName + "]"; + } + + public static class MvMinSorted extends BlockDocValuesReader { + private final SortedNumericDocValues numericDocValues; + + MvMinSorted(SortedNumericDocValues numericDocValues) { + this.numericDocValues = numericDocValues; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + try (BooleanBuilder builder = factory.booleansFromDocValues(docs.count() - offset)) { + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + read(doc, builder); + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + read(docId, (BooleanBuilder) builder); + } + + private void read(int doc, BooleanBuilder builder) throws IOException { + if (false == numericDocValues.advanceExact(doc)) { + builder.appendNull(); + return; + } + builder.appendBoolean(numericDocValues.nextValue() != 0); + } + + @Override + public int docId() { + return numericDocValues.docID(); + } + + @Override + public String toString() { + return "MvMinBooleansFromDocValues.Sorted"; + } + } +} diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoader.java index f97e25170bdc0..34ecc31963d3f 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoader.java @@ -7,11 +7,13 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import org.apache.lucene.index.SortedDocValues; import org.apache.lucene.index.SortedSetDocValues; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.index.mapper.blockloader.docvalues.AbstractBytesRefsFromOrdsBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; import java.io.IOException; diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoader.java new file mode 100644 index 0000000000000..9c6c617e50442 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoader.java @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.SortedNumericDocValues; +import org.elasticsearch.index.mapper.blockloader.docvalues.AbstractDoublesFromDocValuesBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; + +import java.io.IOException; + +/** + * Loads the MIN {@code double} in each doc. + */ +public class MvMinDoublesFromDocValuesBlockLoader extends AbstractDoublesFromDocValuesBlockLoader { + public MvMinDoublesFromDocValuesBlockLoader(String fieldName, BlockDocValuesReader.ToDouble toDouble) { + super(fieldName, toDouble); + } + + @Override + protected AllReader singletonReader(NumericDocValues docValues, BlockDocValuesReader.ToDouble toDouble) { + return new Singleton(docValues, toDouble); + } + + @Override + protected AllReader sortedReader(SortedNumericDocValues docValues, BlockDocValuesReader.ToDouble toDouble) { + return new MvMaxSorted(docValues, toDouble); + } + + @Override + public String toString() { + return "DoublesFromDocValues[" + fieldName + "]"; + } + + public static class MvMaxSorted extends BlockDocValuesReader { + private final SortedNumericDocValues numericDocValues; + private final ToDouble toDouble; + + MvMaxSorted(SortedNumericDocValues numericDocValues, ToDouble toDouble) { + this.numericDocValues = numericDocValues; + this.toDouble = toDouble; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + try (DoubleBuilder builder = factory.doublesFromDocValues(docs.count() - offset)) { + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + read(doc, builder); + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + read(docId, (DoubleBuilder) builder); + } + + private void read(int doc, DoubleBuilder builder) throws IOException { + if (false == numericDocValues.advanceExact(doc)) { + builder.appendNull(); + return; + } + builder.appendDouble(toDouble.convert(numericDocValues.nextValue())); + } + + @Override + public int docId() { + return numericDocValues.docID(); + } + + @Override + public String toString() { + return "MvMinDoublesFromDocValues.Sorted"; + } + } +} diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoader.java index 23f3ad8fb34f4..2c39bacdff838 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoader.java @@ -7,10 +7,12 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import org.apache.lucene.index.NumericDocValues; import org.apache.lucene.index.SortedNumericDocValues; +import org.elasticsearch.index.mapper.blockloader.docvalues.AbstractIntsFromDocValuesBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; import java.io.IOException; diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoader.java new file mode 100644 index 0000000000000..dba1ac8f631f8 --- /dev/null +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoader.java @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.index.SortedNumericDocValues; +import org.elasticsearch.index.mapper.blockloader.docvalues.AbstractLongsFromDocValuesBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; + +import java.io.IOException; + +/** + * Loads the MIN {@code long} in each doc. + */ +public class MvMinLongsFromDocValuesBlockLoader extends AbstractLongsFromDocValuesBlockLoader { + public MvMinLongsFromDocValuesBlockLoader(String fieldName) { + super(fieldName); + } + + @Override + protected AllReader singletonReader(NumericDocValues docValues) { + return new Singleton(docValues); + } + + @Override + protected AllReader sortedReader(SortedNumericDocValues docValues) { + return new MvMaxSorted(docValues); + } + + @Override + public String toString() { + return "LongsFromDocValues[" + fieldName + "]"; + } + + public static class MvMaxSorted extends BlockDocValuesReader { + private final SortedNumericDocValues numericDocValues; + + MvMaxSorted(SortedNumericDocValues numericDocValues) { + this.numericDocValues = numericDocValues; + } + + @Override + public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { + try (LongBuilder builder = factory.longsFromDocValues(docs.count() - offset)) { + for (int i = offset; i < docs.count(); i++) { + int doc = docs.get(i); + read(doc, builder); + } + return builder.build(); + } + } + + @Override + public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { + read(docId, (LongBuilder) builder); + } + + private void read(int doc, LongBuilder builder) throws IOException { + if (false == numericDocValues.advanceExact(doc)) { + builder.appendNull(); + return; + } + builder.appendLong(numericDocValues.nextValue()); + } + + @Override + public int docId() { + return numericDocValues.docID(); + } + + @Override + public String toString() { + return "MvMinLongsFromDocValues.Sorted"; + } + } +} diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoader.java index 59a110fd8627a..ba870329e7bef 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoader.java @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import org.apache.lucene.index.DocValues; import org.apache.lucene.index.LeafReaderContext; @@ -16,6 +16,8 @@ import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.RamUsageEstimator; import org.apache.lucene.util.UnicodeUtil; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; +import org.elasticsearch.index.mapper.blockloader.docvalues.Warnings; import java.io.IOException; import java.util.Arrays; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractBooleansFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractBooleansFromDocValuesBlockLoaderTests.java new file mode 100644 index 0000000000000..55e8191204cfa --- /dev/null +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractBooleansFromDocValuesBlockLoaderTests.java @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.document.SortedNumericDocValuesField; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexableField; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.store.Directory; +import org.apache.lucene.tests.index.RandomIndexWriter; +import org.elasticsearch.index.mapper.BlockLoader; +import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.test.ESTestCase; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public abstract class AbstractBooleansFromDocValuesBlockLoaderTests extends ESTestCase { + @ParametersFactory(argumentFormatting = "blockAtATime=%s, multiValues=%s, missingValues=%s") + public static List parameters() throws IOException { + List parameters = new ArrayList<>(); + for (boolean blockAtATime : new boolean[] { true, false }) { + for (boolean multiValues : new boolean[] { true, false }) { + for (boolean missingValues : new boolean[] { true, false }) { + parameters.add(new Object[] { blockAtATime, multiValues, missingValues }); + } + } + } + return parameters; + } + + protected final boolean blockAtATime; + protected final boolean multiValues; + protected final boolean missingValues; + + public AbstractBooleansFromDocValuesBlockLoaderTests(boolean blockAtATime, boolean multiValues, boolean missingValues) { + this.blockAtATime = blockAtATime; + this.multiValues = multiValues; + this.missingValues = missingValues; + } + + protected abstract void innerTest(LeafReaderContext ctx, int mvCount) throws IOException; + + public void test() throws IOException { + int mvCount = 0; + try (Directory dir = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), dir)) { + int docCount = 10_000; + for (int i = 0; i < docCount; i++) { + List doc = new ArrayList<>(2); + doc.add(field(i)); + if (multiValues && i % 100 == 0) { + doc.add(field((i % 100) + 1)); + mvCount++; + } + iw.addDocument(doc); + } + if (missingValues) { + iw.addDocument(List.of()); + } + iw.forceMerge(1); + try (DirectoryReader dr = iw.getReader()) { + LeafReaderContext ctx = getOnlyLeafReader(dr).getContext(); + innerTest(ctx, mvCount); + } + } + } + + protected final TestBlock read(BlockLoader loader, BlockLoader.AllReader reader, LeafReaderContext ctx, BlockLoader.Docs docs) + throws IOException { + BlockLoader.AllReader toUse = blockAtATime + ? reader + : new ForceDocAtATime(() -> loader.builder(TestBlock.factory(), docs.count()), reader); + + return (TestBlock) toUse.read(TestBlock.factory(), docs, 0, false); + } + + private static SortedNumericDocValuesField field(int v) { + return new SortedNumericDocValuesField("field", v % 4 == 0 ? 1 : 0); + } +} diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractDoublesFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractDoublesFromDocValuesBlockLoaderTests.java new file mode 100644 index 0000000000000..5e86878118fd3 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractDoublesFromDocValuesBlockLoaderTests.java @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.document.DoubleField; +import org.apache.lucene.document.Field; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexableField; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.store.Directory; +import org.apache.lucene.tests.index.RandomIndexWriter; +import org.elasticsearch.index.mapper.BlockLoader; +import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.test.ESTestCase; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public abstract class AbstractDoublesFromDocValuesBlockLoaderTests extends ESTestCase { + @ParametersFactory(argumentFormatting = "blockAtATime=%s, multiValues=%s, missingValues=%s") + public static List parameters() throws IOException { + List parameters = new ArrayList<>(); + for (boolean blockAtATime : new boolean[] { true, false }) { + for (boolean multiValues : new boolean[] { true, false }) { + for (boolean missingValues : new boolean[] { true, false }) { + parameters.add(new Object[] { blockAtATime, multiValues, missingValues }); + } + } + } + return parameters; + } + + protected final boolean blockAtATime; + protected final boolean multiValues; + protected final boolean missingValues; + + public AbstractDoublesFromDocValuesBlockLoaderTests(boolean blockAtATime, boolean multiValues, boolean missingValues) { + this.blockAtATime = blockAtATime; + this.multiValues = multiValues; + this.missingValues = missingValues; + } + + protected abstract void innerTest(LeafReaderContext ctx, int mvCount) throws IOException; + + public void test() throws IOException { + int mvCount = 0; + try (Directory dir = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), dir)) { + int docCount = 10_000; + for (int i = 0; i < docCount; i++) { + List doc = new ArrayList<>(2); + doc.add(field(i)); + if (multiValues && i % 100 == 0) { + doc.add(field((i % 100) + 1)); + mvCount++; + } + iw.addDocument(doc); + } + if (missingValues) { + iw.addDocument(List.of()); + } + iw.forceMerge(1); + try (DirectoryReader dr = iw.getReader()) { + LeafReaderContext ctx = getOnlyLeafReader(dr).getContext(); + innerTest(ctx, mvCount); + } + } + } + + protected final TestBlock read(BlockLoader loader, BlockLoader.AllReader reader, LeafReaderContext ctx, BlockLoader.Docs docs) + throws IOException { + BlockLoader.AllReader toUse = blockAtATime + ? reader + : new ForceDocAtATime(() -> loader.builder(TestBlock.factory(), docs.count()), reader); + + return (TestBlock) toUse.read(TestBlock.factory(), docs, 0, false); + } + + private static DoubleField field(int i) { + return new DoubleField("field", i * 1.1, Field.Store.NO); + } +} diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractFromOrdsBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractFromOrdsBlockLoaderTests.java index 78e8b42e376bb..507f8f430457b 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractFromOrdsBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractFromOrdsBlockLoaderTests.java @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractIntsFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractIntsFromDocValuesBlockLoaderTests.java index fbd9efb4f2110..96316242d0f5f 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractIntsFromDocValuesBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractIntsFromDocValuesBlockLoaderTests.java @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractLongsFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractLongsFromDocValuesBlockLoaderTests.java new file mode 100644 index 0000000000000..b714e0268959c --- /dev/null +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/AbstractLongsFromDocValuesBlockLoaderTests.java @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.apache.lucene.document.Field; +import org.apache.lucene.document.LongField; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.IndexableField; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.store.Directory; +import org.apache.lucene.tests.index.RandomIndexWriter; +import org.elasticsearch.index.mapper.BlockLoader; +import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.test.ESTestCase; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public abstract class AbstractLongsFromDocValuesBlockLoaderTests extends ESTestCase { + @ParametersFactory(argumentFormatting = "blockAtATime=%s, multiValues=%s, missingValues=%s") + public static List parameters() throws IOException { + List parameters = new ArrayList<>(); + for (boolean blockAtATime : new boolean[] { true, false }) { + for (boolean multiValues : new boolean[] { true, false }) { + for (boolean missingValues : new boolean[] { true, false }) { + parameters.add(new Object[] { blockAtATime, multiValues, missingValues }); + } + } + } + return parameters; + } + + protected final boolean blockAtATime; + protected final boolean multiValues; + protected final boolean missingValues; + + public AbstractLongsFromDocValuesBlockLoaderTests(boolean blockAtATime, boolean multiValues, boolean missingValues) { + this.blockAtATime = blockAtATime; + this.multiValues = multiValues; + this.missingValues = missingValues; + } + + protected abstract void innerTest(LeafReaderContext ctx, int mvCount) throws IOException; + + public void test() throws IOException { + int mvCount = 0; + try (Directory dir = newDirectory(); RandomIndexWriter iw = new RandomIndexWriter(random(), dir)) { + int docCount = 10_000; + for (int i = 0; i < docCount; i++) { + List doc = new ArrayList<>(2); + doc.add(field(i)); + if (multiValues && i % 100 == 0) { + doc.add(field((i % 100) + 1)); + mvCount++; + } + iw.addDocument(doc); + } + if (missingValues) { + iw.addDocument(List.of()); + } + iw.forceMerge(1); + try (DirectoryReader dr = iw.getReader()) { + LeafReaderContext ctx = getOnlyLeafReader(dr).getContext(); + innerTest(ctx, mvCount); + } + } + } + + protected final TestBlock read(BlockLoader loader, BlockLoader.AllReader reader, LeafReaderContext ctx, BlockLoader.Docs docs) + throws IOException { + BlockLoader.AllReader toUse = blockAtATime + ? reader + : new ForceDocAtATime(() -> loader.builder(TestBlock.factory(), docs.count()), reader); + + return (TestBlock) toUse.read(TestBlock.factory(), docs, 0, false); + } + + private static LongField field(int i) { + return new LongField("field", i * 10001L, Field.Store.NO); + } +} diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/ForceDocAtATime.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/ForceDocAtATime.java index 0a8ffc7ba2941..78d0b469cbb2b 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/ForceDocAtATime.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/ForceDocAtATime.java @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import org.elasticsearch.index.mapper.BlockLoader; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MockWarnings.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MockWarnings.java index cfb9ffc93fc76..282b7722a32f9 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MockWarnings.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MockWarnings.java @@ -7,7 +7,9 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.elasticsearch.index.mapper.blockloader.docvalues.Warnings; import java.util.ArrayList; import java.util.List; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansFromDocValuesBlockLoaderTests.java new file mode 100644 index 0000000000000..6a806576f58bf --- /dev/null +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansFromDocValuesBlockLoaderTests.java @@ -0,0 +1,81 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.index.mapper.BlockLoader; +import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.index.mapper.blockloader.docvalues.BooleansBlockLoader; +import org.hamcrest.Matcher; + +import java.io.IOException; +import java.util.List; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasToString; +import static org.hamcrest.Matchers.nullValue; + +public class MvMaxBooleansFromDocValuesBlockLoaderTests extends AbstractBooleansFromDocValuesBlockLoaderTests { + public MvMaxBooleansFromDocValuesBlockLoaderTests(boolean blockAtATime, boolean multiValues, boolean missingValues) { + super(blockAtATime, multiValues, missingValues); + } + + @Override + protected void innerTest(LeafReaderContext ctx, int mvCount) throws IOException { + var booleansLoader = new BooleansBlockLoader("field"); + var mvMaxBooleansLoader = new MvMaxBooleansBlockLoader("field"); + + var booleansReader = booleansLoader.reader(ctx); + var mvMaxBooleansReader = mvMaxBooleansLoader.reader(ctx); + assertThat(mvMaxBooleansReader, readerMatcher()); + BlockLoader.Docs docs = TestBlock.docs(ctx); + try ( + TestBlock doubles = read(booleansLoader, booleansReader, ctx, docs); + TestBlock maxDoubles = read(mvMaxBooleansLoader, mvMaxBooleansReader, ctx, docs); + ) { + checkBlocks(doubles, maxDoubles); + } + + booleansReader = booleansLoader.reader(ctx); + mvMaxBooleansReader = mvMaxBooleansLoader.reader(ctx); + for (int i = 0; i < ctx.reader().numDocs(); i += 10) { + int[] docsArray = new int[Math.min(10, ctx.reader().numDocs() - i)]; + for (int d = 0; d < docsArray.length; d++) { + docsArray[d] = i + d; + } + docs = TestBlock.docs(docsArray); + try ( + TestBlock booleans = read(booleansLoader, booleansReader, ctx, docs); + TestBlock maxBooleans = read(mvMaxBooleansLoader, mvMaxBooleansReader, ctx, docs); + ) { + checkBlocks(booleans, maxBooleans); + } + } + } + + private Matcher readerMatcher() { + if (multiValues) { + return hasToString("MvMaxBooleansFromDocValues.Sorted"); + } + return hasToString("BooleansFromDocValues.Singleton"); + } + + private void checkBlocks(TestBlock booleans, TestBlock mvMax) { + for (int i = 0; i < booleans.size(); i++) { + Object v = booleans.get(i); + if (v == null) { + assertThat(mvMax.get(i), nullValue()); + continue; + } + Boolean max = (Boolean) (v instanceof List l ? l.stream().anyMatch(b -> (Boolean) b) : v); + assertThat(mvMax.get(i), equalTo(max)); + } + } +} diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoaderTests.java index 99adec4373187..707fa621c2e5a 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBytesRefsFromOrdsBlockLoaderTests.java @@ -7,13 +7,13 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.util.BytesRef; import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.index.mapper.TestBlock; -import org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxBytesRefsFromOrdsBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BytesRefsFromOrdsBlockLoader; import org.hamcrest.Matcher; import java.io.IOException; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoaderTests.java new file mode 100644 index 0000000000000..bbf4317b83660 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoaderTests.java @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.index.mapper.BlockLoader; +import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.index.mapper.blockloader.docvalues.DoublesBlockLoader; +import org.hamcrest.Matcher; + +import java.io.IOException; +import java.util.Comparator; +import java.util.List; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasToString; +import static org.hamcrest.Matchers.nullValue; + +public class MvMaxDoublesFromDocValuesBlockLoaderTests extends AbstractIntsFromDocValuesBlockLoaderTests { + public MvMaxDoublesFromDocValuesBlockLoaderTests(boolean blockAtATime, boolean multiValues, boolean missingValues) { + super(blockAtATime, multiValues, missingValues); + } + + @Override + protected void innerTest(LeafReaderContext ctx, int mvCount) throws IOException { + var doublesLoader = new DoublesBlockLoader("field", Double::longBitsToDouble); + var mvMaxDoublesLoader = new MvMaxDoublesFromDocValuesBlockLoader("field", Double::longBitsToDouble); + + var doublesReader = doublesLoader.reader(ctx); + var mvMaxDoublesReader = mvMaxDoublesLoader.reader(ctx); + assertThat(mvMaxDoublesReader, readerMatcher()); + BlockLoader.Docs docs = TestBlock.docs(ctx); + try ( + TestBlock doubles = read(doublesLoader, doublesReader, ctx, docs); + TestBlock maxDoubles = read(mvMaxDoublesLoader, mvMaxDoublesReader, ctx, docs); + ) { + checkBlocks(doubles, maxDoubles); + } + + doublesReader = doublesLoader.reader(ctx); + mvMaxDoublesReader = mvMaxDoublesLoader.reader(ctx); + for (int i = 0; i < ctx.reader().numDocs(); i += 10) { + int[] docsArray = new int[Math.min(10, ctx.reader().numDocs() - i)]; + for (int d = 0; d < docsArray.length; d++) { + docsArray[d] = i + d; + } + docs = TestBlock.docs(docsArray); + try ( + TestBlock doubles = read(doublesLoader, doublesReader, ctx, docs); + TestBlock maxDoubles = read(mvMaxDoublesLoader, mvMaxDoublesReader, ctx, docs); + ) { + checkBlocks(doubles, maxDoubles); + } + } + } + + private Matcher readerMatcher() { + if (multiValues) { + return hasToString("MvMaxDoublesFromDocValues.Sorted"); + } + return hasToString("DoublesFromDocValues.Singleton"); + } + + private void checkBlocks(TestBlock doubles, TestBlock mvMax) { + for (int i = 0; i < doubles.size(); i++) { + Object v = doubles.get(i); + if (v == null) { + assertThat(mvMax.get(i), nullValue()); + continue; + } + Double max = (Double) (v instanceof List l ? l.stream().map(b -> (Double) b).max(Comparator.naturalOrder()).get() : v); + assertThat(mvMax.get(i), equalTo(max)); + } + } +} diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoaderTests.java index 83ffc5007afd2..1adf2c0747c23 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoaderTests.java @@ -7,12 +7,12 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import org.apache.lucene.index.LeafReaderContext; import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.index.mapper.TestBlock; -import org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxIntsFromDocValuesBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.IntsBlockLoader; import org.hamcrest.Matcher; import java.io.IOException; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoaderTests.java new file mode 100644 index 0000000000000..b1672584b1da4 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoaderTests.java @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.index.mapper.BlockLoader; +import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.index.mapper.blockloader.docvalues.LongsBlockLoader; +import org.hamcrest.Matcher; + +import java.io.IOException; +import java.util.Comparator; +import java.util.List; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasToString; +import static org.hamcrest.Matchers.nullValue; + +public class MvMaxLongsFromDocValuesBlockLoaderTests extends AbstractIntsFromDocValuesBlockLoaderTests { + public MvMaxLongsFromDocValuesBlockLoaderTests(boolean blockAtATime, boolean multiValues, boolean missingValues) { + super(blockAtATime, multiValues, missingValues); + } + + @Override + protected void innerTest(LeafReaderContext ctx, int mvCount) throws IOException { + var longsLoader = new LongsBlockLoader("field"); + var mvMaxLongsLoader = new MvMaxLongsFromDocValuesBlockLoader("field"); + + var longsReader = longsLoader.reader(ctx); + var mvMaxLongsReader = mvMaxLongsLoader.reader(ctx); + assertThat(mvMaxLongsReader, readerMatcher()); + BlockLoader.Docs docs = TestBlock.docs(ctx); + try ( + TestBlock longs = read(longsLoader, longsReader, ctx, docs); + TestBlock maxLongs = read(mvMaxLongsLoader, mvMaxLongsReader, ctx, docs); + ) { + checkBlocks(longs, maxLongs); + } + + longsReader = longsLoader.reader(ctx); + mvMaxLongsReader = mvMaxLongsLoader.reader(ctx); + for (int i = 0; i < ctx.reader().numDocs(); i += 10) { + int[] docsArray = new int[Math.min(10, ctx.reader().numDocs() - i)]; + for (int d = 0; d < docsArray.length; d++) { + docsArray[d] = i + d; + } + docs = TestBlock.docs(docsArray); + try ( + TestBlock longs = read(longsLoader, longsReader, ctx, docs); + TestBlock maxLongs = read(mvMaxLongsLoader, mvMaxLongsReader, ctx, docs); + ) { + checkBlocks(longs, maxLongs); + } + } + } + + private Matcher readerMatcher() { + if (multiValues) { + return hasToString("MvMaxLongsFromDocValues.Sorted"); + } + return hasToString("LongsFromDocValues.Singleton"); + } + + private void checkBlocks(TestBlock longs, TestBlock mvMax) { + for (int i = 0; i < longs.size(); i++) { + Object v = longs.get(i); + if (v == null) { + assertThat(mvMax.get(i), nullValue()); + continue; + } + Long max = (Long) (v instanceof List l ? l.stream().map(b -> (Long) b).max(Comparator.naturalOrder()).get() : v); + assertThat(mvMax.get(i), equalTo(max)); + } + } +} diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansFromDocValuesBlockLoaderTests.java new file mode 100644 index 0000000000000..ede0d197fd76f --- /dev/null +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansFromDocValuesBlockLoaderTests.java @@ -0,0 +1,81 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.index.mapper.BlockLoader; +import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.index.mapper.blockloader.docvalues.BooleansBlockLoader; +import org.hamcrest.Matcher; + +import java.io.IOException; +import java.util.List; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasToString; +import static org.hamcrest.Matchers.nullValue; + +public class MvMinBooleansFromDocValuesBlockLoaderTests extends AbstractBooleansFromDocValuesBlockLoaderTests { + public MvMinBooleansFromDocValuesBlockLoaderTests(boolean blockAtATime, boolean multiValues, boolean missingValues) { + super(blockAtATime, multiValues, missingValues); + } + + @Override + protected void innerTest(LeafReaderContext ctx, int mvCount) throws IOException { + var booleansLoader = new BooleansBlockLoader("field"); + var mvMinBooleansLoader = new MvMinBooleansBlockLoader("field"); + + var booleansReader = booleansLoader.reader(ctx); + var mvMinBooleansReader = mvMinBooleansLoader.reader(ctx); + assertThat(mvMinBooleansReader, readerMatcher()); + BlockLoader.Docs docs = TestBlock.docs(ctx); + try ( + TestBlock doubles = read(booleansLoader, booleansReader, ctx, docs); + TestBlock minDoubles = read(mvMinBooleansLoader, mvMinBooleansReader, ctx, docs); + ) { + checkBlocks(doubles, minDoubles); + } + + booleansReader = booleansLoader.reader(ctx); + mvMinBooleansReader = mvMinBooleansLoader.reader(ctx); + for (int i = 0; i < ctx.reader().numDocs(); i += 10) { + int[] docsArray = new int[Math.min(10, ctx.reader().numDocs() - i)]; + for (int d = 0; d < docsArray.length; d++) { + docsArray[d] = i + d; + } + docs = TestBlock.docs(docsArray); + try ( + TestBlock booleans = read(booleansLoader, booleansReader, ctx, docs); + TestBlock minBooleans = read(mvMinBooleansLoader, mvMinBooleansReader, ctx, docs); + ) { + checkBlocks(booleans, minBooleans); + } + } + } + + private Matcher readerMatcher() { + if (multiValues) { + return hasToString("MvMinBooleansFromDocValues.Sorted"); + } + return hasToString("BooleansFromDocValues.Singleton"); + } + + private void checkBlocks(TestBlock booleans, TestBlock mvMin) { + for (int i = 0; i < booleans.size(); i++) { + Object v = booleans.get(i); + if (v == null) { + assertThat(mvMin.get(i), nullValue()); + continue; + } + Boolean max = (Boolean) (v instanceof List l ? l.stream().allMatch(b -> (Boolean) b) : v); + assertThat(mvMin.get(i), equalTo(max)); + } + } +} diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoaderTests.java index 2515c6c4155fa..ff3e47b249db6 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBytesRefsFromOrdsBlockLoaderTests.java @@ -7,13 +7,13 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.util.BytesRef; import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.index.mapper.TestBlock; -import org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMinBytesRefsFromOrdsBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BytesRefsFromOrdsBlockLoader; import org.hamcrest.Matcher; import java.io.IOException; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoaderTests.java new file mode 100644 index 0000000000000..6f13ff5e471cc --- /dev/null +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoaderTests.java @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.index.mapper.BlockLoader; +import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.index.mapper.blockloader.docvalues.DoublesBlockLoader; +import org.hamcrest.Matcher; + +import java.io.IOException; +import java.util.Comparator; +import java.util.List; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasToString; +import static org.hamcrest.Matchers.nullValue; + +public class MvMinDoublesFromDocValuesBlockLoaderTests extends AbstractIntsFromDocValuesBlockLoaderTests { + public MvMinDoublesFromDocValuesBlockLoaderTests(boolean blockAtATime, boolean multiValues, boolean missingValues) { + super(blockAtATime, multiValues, missingValues); + } + + @Override + protected void innerTest(LeafReaderContext ctx, int mvCount) throws IOException { + var doublesLoader = new DoublesBlockLoader("field", Double::longBitsToDouble); + var mvMinDoublesLoader = new MvMinDoublesFromDocValuesBlockLoader("field", Double::longBitsToDouble); + + var doublesReader = doublesLoader.reader(ctx); + var mvMinDoublesReader = mvMinDoublesLoader.reader(ctx); + assertThat(mvMinDoublesReader, readerMatcher()); + BlockLoader.Docs docs = TestBlock.docs(ctx); + try ( + TestBlock doubles = read(doublesLoader, doublesReader, ctx, docs); + TestBlock minDoubles = read(mvMinDoublesLoader, mvMinDoublesReader, ctx, docs); + ) { + checkBlocks(doubles, minDoubles); + } + + doublesReader = doublesLoader.reader(ctx); + mvMinDoublesReader = mvMinDoublesLoader.reader(ctx); + for (int i = 0; i < ctx.reader().numDocs(); i += 10) { + int[] docsArray = new int[Math.min(10, ctx.reader().numDocs() - i)]; + for (int d = 0; d < docsArray.length; d++) { + docsArray[d] = i + d; + } + docs = TestBlock.docs(docsArray); + try ( + TestBlock doubles = read(doublesLoader, doublesReader, ctx, docs); + TestBlock minDoubles = read(mvMinDoublesLoader, mvMinDoublesReader, ctx, docs); + ) { + checkBlocks(doubles, minDoubles); + } + } + } + + private Matcher readerMatcher() { + if (multiValues) { + return hasToString("MvMinDoublesFromDocValues.Sorted"); + } + return hasToString("DoublesFromDocValues.Singleton"); + } + + private void checkBlocks(TestBlock doubles, TestBlock mvMin) { + for (int i = 0; i < doubles.size(); i++) { + Object v = doubles.get(i); + if (v == null) { + assertThat(mvMin.get(i), nullValue()); + continue; + } + Double min = (Double) (v instanceof List l ? l.stream().map(b -> (Double) b).min(Comparator.naturalOrder()).get() : v); + assertThat(mvMin.get(i), equalTo(min)); + } + } +} diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoaderTests.java index 7a7c947a826db..0e2bfe719ebbc 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoaderTests.java @@ -7,12 +7,12 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import org.apache.lucene.index.LeafReaderContext; import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.index.mapper.TestBlock; -import org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMinIntsFromDocValuesBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.IntsBlockLoader; import org.hamcrest.Matcher; import java.io.IOException; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoaderTests.java new file mode 100644 index 0000000000000..923833fee5cb8 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoaderTests.java @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; + +import org.apache.lucene.index.LeafReaderContext; +import org.elasticsearch.index.mapper.BlockLoader; +import org.elasticsearch.index.mapper.TestBlock; +import org.elasticsearch.index.mapper.blockloader.docvalues.LongsBlockLoader; +import org.hamcrest.Matcher; + +import java.io.IOException; +import java.util.Comparator; +import java.util.List; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasToString; +import static org.hamcrest.Matchers.nullValue; + +public class MvMinLongsFromDocValuesBlockLoaderTests extends AbstractIntsFromDocValuesBlockLoaderTests { + public MvMinLongsFromDocValuesBlockLoaderTests(boolean blockAtATime, boolean multiValues, boolean missingValues) { + super(blockAtATime, multiValues, missingValues); + } + + @Override + protected void innerTest(LeafReaderContext ctx, int mvCount) throws IOException { + var longsLoader = new LongsBlockLoader("field"); + var mvMinLongsLoader = new MvMinLongsFromDocValuesBlockLoader("field"); + + var longsReader = longsLoader.reader(ctx); + var mvMinLongsReader = mvMinLongsLoader.reader(ctx); + assertThat(mvMinLongsReader, readerMatcher()); + BlockLoader.Docs docs = TestBlock.docs(ctx); + try ( + TestBlock longs = read(longsLoader, longsReader, ctx, docs); + TestBlock minLongs = read(mvMinLongsLoader, mvMinLongsReader, ctx, docs); + ) { + checkBlocks(longs, minLongs); + } + + longsReader = longsLoader.reader(ctx); + mvMinLongsReader = mvMinLongsLoader.reader(ctx); + for (int i = 0; i < ctx.reader().numDocs(); i += 10) { + int[] docsArray = new int[Math.min(10, ctx.reader().numDocs() - i)]; + for (int d = 0; d < docsArray.length; d++) { + docsArray[d] = i + d; + } + docs = TestBlock.docs(docsArray); + try ( + TestBlock longs = read(longsLoader, longsReader, ctx, docs); + TestBlock maxLongs = read(mvMinLongsLoader, mvMinLongsReader, ctx, docs); + ) { + checkBlocks(longs, maxLongs); + } + } + } + + private Matcher readerMatcher() { + if (multiValues) { + return hasToString("MvMinLongsFromDocValues.Sorted"); + } + return hasToString("LongsFromDocValues.Singleton"); + } + + private void checkBlocks(TestBlock longs, TestBlock mvMin) { + for (int i = 0; i < longs.size(); i++) { + Object v = longs.get(i); + if (v == null) { + assertThat(mvMin.get(i), nullValue()); + continue; + } + Long max = (Long) (v instanceof List l ? l.stream().map(b -> (Long) b).min(Comparator.naturalOrder()).get() : v); + assertThat(mvMin.get(i), equalTo(max)); + } + } +} diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java index f65fed1e3a7ab..c90e9975562a6 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java @@ -7,14 +7,14 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -package org.elasticsearch.index.mapper.blockloader.docvalues; +package org.elasticsearch.index.mapper.blockloader.docvalues.fn; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.util.BytesRef; import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.index.mapper.KeywordFieldMapper; import org.elasticsearch.index.mapper.TestBlock; -import org.elasticsearch.index.mapper.blockloader.docvalues.fn.Utf8CodePointsFromOrdsBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.BytesRefsFromOrdsBlockLoader; import org.hamcrest.Matcher; import java.io.IOException; diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/TimeSeriesIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/TimeSeriesIT.java index a501da545d9b6..01b403198ce69 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/TimeSeriesIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/TimeSeriesIT.java @@ -588,10 +588,7 @@ public void testProfile() { assertThat( readMetrics.readersBuilt().keySet(), equalTo( - Set.of( - "_tsid:column_at_a_time:BytesRefsFromOrds.Singleton", - "cpu:column_at_a_time:BlockDocValuesReader.SingletonDoubles" - ) + Set.of("_tsid:column_at_a_time:BytesRefsFromOrds.Singleton", "cpu:column_at_a_time:DoublesFromDocValues.Singleton") ) ); assertThat(ops.get(3).operator(), containsString("TimeSeriesAggregationOperator")); From 175074a349961a0a34fe0e9867f0b6c01e75a9cf Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Mon, 10 Nov 2025 08:55:54 -0500 Subject: [PATCH 4/6] Fixup --- .../AbstractBooleansBlockLoader.java | 3 +++ .../fn/MvMaxBooleansBlockLoader.java | 7 +++++-- .../MvMaxDoublesFromDocValuesBlockLoader.java | 4 ++-- .../fn/MvMaxIntsFromDocValuesBlockLoader.java | 4 ++-- .../MvMaxLongsFromDocValuesBlockLoader.java | 19 +++++++++++-------- .../fn/MvMinBooleansBlockLoader.java | 5 ++++- .../MvMinDoublesFromDocValuesBlockLoader.java | 2 +- .../fn/MvMinIntsFromDocValuesBlockLoader.java | 2 +- .../MvMinLongsFromDocValuesBlockLoader.java | 2 +- 9 files changed, 30 insertions(+), 18 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBooleansBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBooleansBlockLoader.java index 65287b2425925..86f41df634745 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBooleansBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/AbstractBooleansBlockLoader.java @@ -16,6 +16,9 @@ import java.io.IOException; +/** + * Loads {@code boolean}s from doc values. + */ public abstract class AbstractBooleansBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { protected final String fieldName; diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java index d24313d5ae829..42f0c893f8872 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java @@ -16,8 +16,11 @@ import java.io.IOException; -import static org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxLongsFromDocValuesBlockLoader.MvMaxSorted.discardAllButLast; +import static org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxLongsFromDocValuesBlockLoader.discardAllButLast; +/** + * Loads the MAX {@code boolean} in each doc. Think of like {@code ANY}. + */ public class MvMaxBooleansBlockLoader extends AbstractBooleansBlockLoader { public MvMaxBooleansBlockLoader(String fieldName) { super(fieldName); @@ -38,7 +41,7 @@ public String toString() { return "BooleansFromDocValues[" + fieldName + "]"; } - public static class MvMinSorted extends BlockDocValuesReader { + private static class MvMinSorted extends BlockDocValuesReader { private final SortedNumericDocValues numericDocValues; MvMinSorted(SortedNumericDocValues numericDocValues) { diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoader.java index 28b786fc40b03..8082d9d91a0b9 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxDoublesFromDocValuesBlockLoader.java @@ -16,7 +16,7 @@ import java.io.IOException; -import static org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxLongsFromDocValuesBlockLoader.MvMaxSorted.discardAllButLast; +import static org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxLongsFromDocValuesBlockLoader.discardAllButLast; /** * Loads the MAX {@code double} in each doc. @@ -41,7 +41,7 @@ public String toString() { return "DoublesFromDocValues[" + fieldName + "]"; } - public static class MvMaxSorted extends BlockDocValuesReader { + private static class MvMaxSorted extends BlockDocValuesReader { private final SortedNumericDocValues numericDocValues; private final ToDouble toDouble; diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoader.java index 2a56ceb97e126..a3208da019a0f 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxIntsFromDocValuesBlockLoader.java @@ -16,7 +16,7 @@ import java.io.IOException; -import static org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxLongsFromDocValuesBlockLoader.MvMaxSorted.discardAllButLast; +import static org.elasticsearch.index.mapper.blockloader.docvalues.fn.MvMaxLongsFromDocValuesBlockLoader.discardAllButLast; /** * Loads the MAX {@code int} in each doc. @@ -41,7 +41,7 @@ public String toString() { return "IntsFromDocValues[" + fieldName + "]"; } - public static class MvMaxSorted extends BlockDocValuesReader { + private static class MvMaxSorted extends BlockDocValuesReader { private final SortedNumericDocValues numericDocValues; MvMaxSorted(SortedNumericDocValues numericDocValues) { diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoader.java index aefccd8060899..44f4a131f876a 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxLongsFromDocValuesBlockLoader.java @@ -39,7 +39,7 @@ public String toString() { return "LongsFromDocValues[" + fieldName + "]"; } - public static class MvMaxSorted extends BlockDocValuesReader { + private static class MvMaxSorted extends BlockDocValuesReader { private final SortedNumericDocValues numericDocValues; MvMaxSorted(SortedNumericDocValues numericDocValues) { @@ -76,16 +76,19 @@ public int docId() { return numericDocValues.docID(); } - static void discardAllButLast(SortedNumericDocValues numericDocValues) throws IOException { - int count = numericDocValues.docValueCount(); - for (int i = 0; i < count - 1; i++) { - numericDocValues.nextValue(); - } - } - @Override public String toString() { return "MvMaxLongsFromDocValues.Sorted"; } } + + /** + * Discard all doc values but the last ones in this position. + */ + static void discardAllButLast(SortedNumericDocValues numericDocValues) throws IOException { + int count = numericDocValues.docValueCount(); + for (int i = 0; i < count - 1; i++) { + numericDocValues.nextValue(); + } + } } diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansBlockLoader.java index dc396e6eeb3a4..db1ca01840cba 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinBooleansBlockLoader.java @@ -16,6 +16,9 @@ import java.io.IOException; +/** + * Loads the MIN {@code boolean} in each doc. Think of it like {@code ALL}. + */ public class MvMinBooleansBlockLoader extends AbstractBooleansBlockLoader { public MvMinBooleansBlockLoader(String fieldName) { super(fieldName); @@ -36,7 +39,7 @@ public String toString() { return "BooleansFromDocValues[" + fieldName + "]"; } - public static class MvMinSorted extends BlockDocValuesReader { + private static class MvMinSorted extends BlockDocValuesReader { private final SortedNumericDocValues numericDocValues; MvMinSorted(SortedNumericDocValues numericDocValues) { diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoader.java index 9c6c617e50442..17f39007aadeb 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinDoublesFromDocValuesBlockLoader.java @@ -39,7 +39,7 @@ public String toString() { return "DoublesFromDocValues[" + fieldName + "]"; } - public static class MvMaxSorted extends BlockDocValuesReader { + private static class MvMaxSorted extends BlockDocValuesReader { private final SortedNumericDocValues numericDocValues; private final ToDouble toDouble; diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoader.java index 2c39bacdff838..db1474cc35e8c 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinIntsFromDocValuesBlockLoader.java @@ -39,7 +39,7 @@ public String toString() { return "IntsFromDocValues[" + fieldName + "]"; } - public static class MvMinSorted extends BlockDocValuesReader { + private static class MvMinSorted extends BlockDocValuesReader { private final SortedNumericDocValues numericDocValues; MvMinSorted(SortedNumericDocValues numericDocValues) { diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoader.java index dba1ac8f631f8..1094667bb1c04 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMinLongsFromDocValuesBlockLoader.java @@ -39,7 +39,7 @@ public String toString() { return "LongsFromDocValues[" + fieldName + "]"; } - public static class MvMaxSorted extends BlockDocValuesReader { + private static class MvMaxSorted extends BlockDocValuesReader { private final SortedNumericDocValues numericDocValues; MvMaxSorted(SortedNumericDocValues numericDocValues) { From bb8bf957b02d16778793d26dfd0e4e0ad2b5c8cd Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Mon, 10 Nov 2025 15:22:05 -0500 Subject: [PATCH 5/6] Merge --- .../org/elasticsearch/index/mapper/KeywordFieldMapper.java | 2 +- .../docvalues/fn/Utf8CodePointsFromOrdsBlockLoader.java | 2 +- .../docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java | 2 +- .../esql/expression/function/vector/CosineSimilarity.java | 5 +++++ .../xpack/esql/expression/function/vector/DotProduct.java | 5 +++++ .../xpack/esql/expression/function/vector/Hamming.java | 5 +++++ .../xpack/esql/expression/function/vector/L1Norm.java | 5 +++++ .../xpack/esql/expression/function/vector/L2Norm.java | 5 +++++ 8 files changed, 28 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java index 328988e235fcb..c9295762ba8fe 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java @@ -61,7 +61,7 @@ import org.elasticsearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData; import org.elasticsearch.index.mapper.blockloader.BlockLoaderFunctionConfig; import org.elasticsearch.index.mapper.blockloader.docvalues.BytesRefsFromOrdsBlockLoader; -import org.elasticsearch.index.mapper.blockloader.docvalues.Utf8CodePointsFromOrdsBlockLoader; +import org.elasticsearch.index.mapper.blockloader.docvalues.fn.Utf8CodePointsFromOrdsBlockLoader; import org.elasticsearch.index.query.AutomatonQueryWithDescription; import org.elasticsearch.index.query.SearchExecutionContext; import org.elasticsearch.index.similarity.SimilarityProvider; diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoader.java index 111cc3bc638de..d317688eda997 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoader.java @@ -16,8 +16,8 @@ import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.RamUsageEstimator; import org.apache.lucene.util.UnicodeUtil; -import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; import org.elasticsearch.index.mapper.blockloader.Warnings; +import org.elasticsearch.index.mapper.blockloader.docvalues.BlockDocValuesReader; import java.io.IOException; import java.util.Arrays; diff --git a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java index 37c789803dd3a..3ec8835324118 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/Utf8CodePointsFromOrdsBlockLoaderTests.java @@ -14,8 +14,8 @@ import org.elasticsearch.index.mapper.BlockLoader; import org.elasticsearch.index.mapper.KeywordFieldMapper; import org.elasticsearch.index.mapper.TestBlock; -import org.elasticsearch.index.mapper.blockloader.docvalues.BytesRefsFromOrdsBlockLoader; import org.elasticsearch.index.mapper.blockloader.MockWarnings; +import org.elasticsearch.index.mapper.blockloader.docvalues.BytesRefsFromOrdsBlockLoader; import org.hamcrest.Matcher; import java.io.IOException; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/CosineSimilarity.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/CosineSimilarity.java index 665697aa45aed..696475ec69504 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/CosineSimilarity.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/CosineSimilarity.java @@ -46,6 +46,11 @@ public float calculateSimilarity(float[] leftVector, float[] rightVector) { public BlockLoaderFunctionConfig.Function function() { return BlockLoaderFunctionConfig.Function.V_COSINE; } + + @Override + public String toString() { + return "V_COSINE"; + } }; @FunctionInfo( diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/DotProduct.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/DotProduct.java index 790238a0412b8..15eb12e6ef130 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/DotProduct.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/DotProduct.java @@ -47,6 +47,11 @@ public float calculateSimilarity(float[] leftVector, float[] rightVector) { public BlockLoaderFunctionConfig.Function function() { return BlockLoaderFunctionConfig.Function.V_DOT_PRODUCT; } + + @Override + public String toString() { + return "V_DOT_PRODUCT"; + } }; @FunctionInfo( diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/Hamming.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/Hamming.java index 0b85648138ae3..99a3c40ae9c07 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/Hamming.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/Hamming.java @@ -42,6 +42,11 @@ public float calculateSimilarity(float[] leftVector, float[] rightVector) { public BlockLoaderFunctionConfig.Function function() { return BlockLoaderFunctionConfig.Function.V_HAMMING; } + + @Override + public String toString() { + return "V_HAMMING"; + } }; public static final DenseVectorFieldMapper.SimilarityFunction EVALUATOR_SIMILARITY_FUNCTION = new DenseVectorFieldMapper.SimilarityFunction() { diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/L1Norm.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/L1Norm.java index 100d9ca7ac19a..57f1d57834408 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/L1Norm.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/L1Norm.java @@ -55,6 +55,11 @@ public float calculateSimilarity(float[] leftVector, float[] rightVector) { public BlockLoaderFunctionConfig.Function function() { return BlockLoaderFunctionConfig.Function.V_L1NORM; } + + @Override + public String toString() { + return "V_L1_NORM"; + } }; @FunctionInfo( diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/L2Norm.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/L2Norm.java index 453cb6c7f8eaa..ee577dee8c210 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/L2Norm.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/vector/L2Norm.java @@ -43,6 +43,11 @@ public float calculateSimilarity(float[] leftVector, float[] rightVector) { public BlockLoaderFunctionConfig.Function function() { return BlockLoaderFunctionConfig.Function.V_L2NORM; } + + @Override + public String toString() { + return "V_L2_NORM"; + } }; @FunctionInfo( From c20a34f5cbab4f2e315ef347857086425dde3391 Mon Sep 17 00:00:00 2001 From: Nik Everett Date: Tue, 11 Nov 2025 01:26:19 -0500 Subject: [PATCH 6/6] Typo --- .../blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java index 42f0c893f8872..ba193ca5f0d49 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/blockloader/docvalues/fn/MvMaxBooleansBlockLoader.java @@ -33,7 +33,7 @@ protected AllReader singletonReader(NumericDocValues docValues) { @Override protected AllReader sortedReader(SortedNumericDocValues docValues) { - return new MvMinSorted(docValues); + return new MvMaxSorted(docValues); } @Override @@ -41,10 +41,10 @@ public String toString() { return "BooleansFromDocValues[" + fieldName + "]"; } - private static class MvMinSorted extends BlockDocValuesReader { + private static class MvMaxSorted extends BlockDocValuesReader { private final SortedNumericDocValues numericDocValues; - MvMinSorted(SortedNumericDocValues numericDocValues) { + MvMaxSorted(SortedNumericDocValues numericDocValues) { this.numericDocValues = numericDocValues; }