Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

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";
}
}
}
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";
}
}
}
Loading