-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Block loaders for MV_MIN and MV_MAX for keywords #137473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
738976e
Block loaders for MV_MIN and MV_MAX for keywords
nik9000 2bf9269
Fix comment
nik9000 9872f90
Fixup test
nik9000 90e67e4
More tests
nik9000 7b5ee44
More tests
nik9000 1b0d589
Test
nik9000 4528fcc
Compare instead of grab
nik9000 795935d
Ints
nik9000 483261c
Merge branch 'main' into fuse_mv_min_max
nik9000 8fa3db2
Rename
nik9000 2363e73
Merge branch 'main' into fuse_mv_min_max
nik9000 14e21c8
Merge branch 'main' into fuse_mv_min_max
nik9000 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
206 changes: 206 additions & 0 deletions
206
...lasticsearch/index/mapper/blockloader/docvalues/AbstractBytesRefsFromOrdsBlockLoader.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,206 @@ | ||
| /* | ||
| * 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.SortedDocValues; | ||
| import org.apache.lucene.index.SortedSetDocValues; | ||
| import org.apache.lucene.util.BytesRef; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| /** | ||
| * Loads {@code keyword} style fields that are stored as a lookup table. | ||
| */ | ||
| abstract class AbstractBytesRefsFromOrdsBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { | ||
| protected final String fieldName; | ||
|
|
||
| AbstractBytesRefsFromOrdsBlockLoader(String fieldName) { | ||
| this.fieldName = fieldName; | ||
| } | ||
|
|
||
| @Override | ||
| public final BytesRefBuilder builder(BlockFactory factory, int expectedCount) { | ||
| return factory.bytesRefs(expectedCount); | ||
| } | ||
|
|
||
| @Override | ||
| public final AllReader reader(LeafReaderContext context) throws IOException { | ||
| SortedSetDocValues docValues = context.reader().getSortedSetDocValues(fieldName); | ||
| if (docValues != null) { | ||
| SortedDocValues singleton = DocValues.unwrapSingleton(docValues); | ||
| if (singleton != null) { | ||
| return singletonReader(singleton); | ||
| } | ||
| return sortedSetReader(docValues); | ||
| } | ||
| SortedDocValues singleton = context.reader().getSortedDocValues(fieldName); | ||
| if (singleton != null) { | ||
| return singletonReader(singleton); | ||
| } | ||
| return new ConstantNullsReader(); | ||
| } | ||
|
|
||
| protected abstract AllReader singletonReader(SortedDocValues docValues); | ||
|
|
||
| protected abstract AllReader sortedSetReader(SortedSetDocValues docValues); | ||
|
|
||
| protected static class Singleton extends BlockDocValuesReader { | ||
| private final SortedDocValues ordinals; | ||
|
|
||
| Singleton(SortedDocValues ordinals) { | ||
| this.ordinals = ordinals; | ||
| } | ||
|
|
||
| private Block readSingleDoc(BlockFactory factory, int docId) throws IOException { | ||
| if (ordinals.advanceExact(docId)) { | ||
| BytesRef v = ordinals.lookupOrd(ordinals.ordValue()); | ||
| // the returned BytesRef can be reused | ||
| return factory.constantBytes(BytesRef.deepCopyOf(v), 1); | ||
| } else { | ||
| return factory.constantNulls(1); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { | ||
| if (docs.count() - offset == 1) { | ||
| return readSingleDoc(factory, docs.get(offset)); | ||
| } | ||
| if (ordinals instanceof OptionalColumnAtATimeReader direct) { | ||
| Block block = direct.tryRead(factory, docs, offset, nullsFiltered, null, false); | ||
| if (block != null) { | ||
| return block; | ||
| } | ||
| } | ||
| try (var builder = factory.singletonOrdinalsBuilder(ordinals, docs.count() - offset, false)) { | ||
| for (int i = offset; i < docs.count(); i++) { | ||
| int doc = docs.get(i); | ||
| if (ordinals.advanceExact(doc)) { | ||
| builder.appendOrd(ordinals.ordValue()); | ||
| } else { | ||
| builder.appendNull(); | ||
| } | ||
| } | ||
| return builder.build(); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { | ||
| if (ordinals.advanceExact(docId)) { | ||
| ((BytesRefBuilder) builder).appendBytesRef(ordinals.lookupOrd(ordinals.ordValue())); | ||
| } else { | ||
| builder.appendNull(); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public int docId() { | ||
| return ordinals.docID(); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return "BytesRefsFromOrds.Singleton"; | ||
| } | ||
| } | ||
|
|
||
| protected static class SortedSet extends BlockDocValuesReader { | ||
| private final SortedSetDocValues ordinals; | ||
|
|
||
| SortedSet(SortedSetDocValues ordinals) { | ||
| this.ordinals = ordinals; | ||
| } | ||
|
|
||
| @Override | ||
| public Block read(BlockFactory factory, Docs docs, int offset, boolean nullsFiltered) throws IOException { | ||
| if (docs.count() - offset == 1) { | ||
| return readSingleDoc(factory, docs.get(offset)); | ||
| } | ||
| try (var builder = factory.sortedSetOrdinalsBuilder(ordinals, docs.count() - offset)) { | ||
| for (int i = offset; i < docs.count(); i++) { | ||
| int doc = docs.get(i); | ||
| if (doc < ordinals.docID()) { | ||
| throw new IllegalStateException("docs within same block must be in order"); | ||
| } | ||
| if (ordinals.advanceExact(doc) == false) { | ||
| builder.appendNull(); | ||
| continue; | ||
| } | ||
| int count = ordinals.docValueCount(); | ||
| if (count == 1) { | ||
| builder.appendOrd(Math.toIntExact(ordinals.nextOrd())); | ||
| } else { | ||
| builder.beginPositionEntry(); | ||
| for (int c = 0; c < count; c++) { | ||
| builder.appendOrd(Math.toIntExact(ordinals.nextOrd())); | ||
| } | ||
| builder.endPositionEntry(); | ||
| } | ||
| } | ||
| return builder.build(); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { | ||
| read(docId, (BytesRefBuilder) builder); | ||
| } | ||
|
|
||
| private Block readSingleDoc(BlockFactory factory, int docId) throws IOException { | ||
| if (ordinals.advanceExact(docId) == false) { | ||
| return factory.constantNulls(1); | ||
| } | ||
| int count = ordinals.docValueCount(); | ||
| if (count == 1) { | ||
| BytesRef v = ordinals.lookupOrd(ordinals.nextOrd()); | ||
| return factory.constantBytes(BytesRef.deepCopyOf(v), 1); | ||
| } | ||
| try (var builder = factory.bytesRefsFromDocValues(count)) { | ||
| builder.beginPositionEntry(); | ||
| for (int c = 0; c < count; c++) { | ||
| BytesRef v = ordinals.lookupOrd(ordinals.nextOrd()); | ||
| builder.appendBytesRef(v); | ||
| } | ||
| builder.endPositionEntry(); | ||
| return builder.build(); | ||
| } | ||
| } | ||
|
|
||
| private void read(int docId, BytesRefBuilder builder) throws IOException { | ||
| if (false == ordinals.advanceExact(docId)) { | ||
| builder.appendNull(); | ||
| return; | ||
| } | ||
| int count = ordinals.docValueCount(); | ||
| if (count == 1) { | ||
| builder.appendBytesRef(ordinals.lookupOrd(ordinals.nextOrd())); | ||
| return; | ||
| } | ||
| builder.beginPositionEntry(); | ||
| for (int v = 0; v < count; v++) { | ||
| builder.appendBytesRef(ordinals.lookupOrd(ordinals.nextOrd())); | ||
| } | ||
| builder.endPositionEntry(); | ||
| } | ||
|
|
||
| @Override | ||
| public int docId() { | ||
| return ordinals.docID(); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return "BytesRefsFromOrds.SortedSet"; | ||
| } | ||
| } | ||
| } | ||
159 changes: 159 additions & 0 deletions
159
...lasticsearch/index/mapper/blockloader/docvalues/AbstractIntsFromDocValuesBlockLoader.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 int}s from doc values. | ||
| */ | ||
| public abstract class AbstractIntsFromDocValuesBlockLoader extends BlockDocValuesReader.DocValuesBlockLoader { | ||
| protected final String fieldName; | ||
|
|
||
| AbstractIntsFromDocValuesBlockLoader(String fieldName) { | ||
| this.fieldName = fieldName; | ||
| } | ||
|
|
||
| @Override | ||
| public final Builder builder(BlockFactory factory, int expectedCount) { | ||
| return factory.ints(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 { | ||
| private 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, true); | ||
| if (result != null) { | ||
| return result; | ||
| } | ||
| } | ||
| try (IntBuilder builder = factory.intsFromDocValues(docs.count() - offset)) { | ||
| for (int i = offset; i < docs.count(); i++) { | ||
| int doc = docs.get(i); | ||
| if (numericDocValues.advanceExact(doc)) { | ||
| builder.appendInt(Math.toIntExact(numericDocValues.longValue())); | ||
| } else { | ||
| builder.appendNull(); | ||
| } | ||
| } | ||
| return builder.build(); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void read(int docId, StoredFields storedFields, Builder builder) throws IOException { | ||
| IntBuilder blockBuilder = (IntBuilder) builder; | ||
| if (numericDocValues.advanceExact(docId)) { | ||
| blockBuilder.appendInt(Math.toIntExact(numericDocValues.longValue())); | ||
| } else { | ||
| blockBuilder.appendNull(); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public int docId() { | ||
| return numericDocValues.docID(); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return "IntsFromDocValues.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 (IntBuilder builder = factory.intsFromDocValues(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, (IntBuilder) builder); | ||
| } | ||
|
|
||
| private void read(int doc, IntBuilder builder) throws IOException { | ||
| if (false == numericDocValues.advanceExact(doc)) { | ||
| builder.appendNull(); | ||
| return; | ||
| } | ||
| int count = numericDocValues.docValueCount(); | ||
| if (count == 1) { | ||
| builder.appendInt(Math.toIntExact(numericDocValues.nextValue())); | ||
| return; | ||
| } | ||
| builder.beginPositionEntry(); | ||
| for (int v = 0; v < count; v++) { | ||
| builder.appendInt(Math.toIntExact(numericDocValues.nextValue())); | ||
| } | ||
| builder.endPositionEntry(); | ||
| } | ||
|
|
||
| @Override | ||
| public int docId() { | ||
| return numericDocValues.docID(); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return "IntsFromDocValues.Sorted"; | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!