|
@@ -24,7 +24,6 @@ import org.elasticsearch.compute.data.DocBlock;
|
|
|
import org.elasticsearch.compute.data.DocVector;
|
|
|
import org.elasticsearch.compute.data.IntVector;
|
|
|
import org.elasticsearch.compute.data.Page;
|
|
|
-import org.elasticsearch.compute.data.Vector;
|
|
|
import org.elasticsearch.core.Releasable;
|
|
|
import org.elasticsearch.core.Releasables;
|
|
|
|
|
@@ -44,12 +43,12 @@ import java.util.function.Consumer;
|
|
|
* It's much faster to push queries to the {@link LuceneSourceOperator} or the like, but sometimes this isn't possible. So
|
|
|
* this class is here to save the day.
|
|
|
*/
|
|
|
-public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements Releasable {
|
|
|
+public abstract class LuceneQueryEvaluator<T extends Block.Builder> implements Releasable {
|
|
|
|
|
|
public record ShardConfig(Query query, IndexSearcher searcher) {}
|
|
|
|
|
|
private final BlockFactory blockFactory;
|
|
|
- private final ShardConfig[] shards;
|
|
|
+ protected final ShardConfig[] shards;
|
|
|
|
|
|
private final List<ShardState> perShardState;
|
|
|
|
|
@@ -67,9 +66,9 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
DocVector docs = (DocVector) block.asVector();
|
|
|
try {
|
|
|
if (docs.singleSegmentNonDecreasing()) {
|
|
|
- return evalSingleSegmentNonDecreasing(docs).asBlock();
|
|
|
+ return evalSingleSegmentNonDecreasing(docs);
|
|
|
} else {
|
|
|
- return evalSlow(docs).asBlock();
|
|
|
+ return evalSlow(docs);
|
|
|
}
|
|
|
} catch (IOException e) {
|
|
|
throw new UncheckedIOException(e);
|
|
@@ -106,15 +105,15 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
* common.
|
|
|
* </p>
|
|
|
*/
|
|
|
- private Vector evalSingleSegmentNonDecreasing(DocVector docs) throws IOException {
|
|
|
+ private Block evalSingleSegmentNonDecreasing(DocVector docs) throws IOException {
|
|
|
ShardState shardState = shardState(docs.shards().getInt(0));
|
|
|
SegmentState segmentState = shardState.segmentState(docs.segments().getInt(0));
|
|
|
int min = docs.docs().getInt(0);
|
|
|
int max = docs.docs().getInt(docs.getPositionCount() - 1);
|
|
|
int length = max - min + 1;
|
|
|
- try (T scoreBuilder = createVectorBuilder(blockFactory, docs.getPositionCount())) {
|
|
|
+ try (T scoreBuilder = createBlockBuilder(blockFactory, docs.getPositionCount())) {
|
|
|
if (length == docs.getPositionCount() && length > 1) {
|
|
|
- return segmentState.scoreDense(scoreBuilder, min, max);
|
|
|
+ return segmentState.scoreDense(scoreBuilder, min, max, docs.getPositionCount());
|
|
|
}
|
|
|
return segmentState.scoreSparse(scoreBuilder, docs.docs());
|
|
|
}
|
|
@@ -134,13 +133,13 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
* the order that the {@link DocVector} came in.
|
|
|
* </p>
|
|
|
*/
|
|
|
- private Vector evalSlow(DocVector docs) throws IOException {
|
|
|
+ private Block evalSlow(DocVector docs) throws IOException {
|
|
|
int[] map = docs.shardSegmentDocMapForwards();
|
|
|
// Clear any state flags from the previous run
|
|
|
int prevShard = -1;
|
|
|
int prevSegment = -1;
|
|
|
SegmentState segmentState = null;
|
|
|
- try (T scoreBuilder = createVectorBuilder(blockFactory, docs.getPositionCount())) {
|
|
|
+ try (T scoreBuilder = createBlockBuilder(blockFactory, docs.getPositionCount())) {
|
|
|
for (int i = 0; i < docs.getPositionCount(); i++) {
|
|
|
int shard = docs.shards().getInt(docs.shards().getInt(map[i]));
|
|
|
int segment = docs.segments().getInt(map[i]);
|
|
@@ -156,7 +155,7 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
segmentState.scoreSingleDocWithScorer(scoreBuilder, docs.docs().getInt(map[i]));
|
|
|
}
|
|
|
}
|
|
|
- try (Vector outOfOrder = scoreBuilder.build()) {
|
|
|
+ try (Block outOfOrder = scoreBuilder.build()) {
|
|
|
return outOfOrder.filter(docs.shardSegmentDocMapBackwards());
|
|
|
}
|
|
|
}
|
|
@@ -247,9 +246,9 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
* Score a range using the {@link BulkScorer}. This should be faster
|
|
|
* than using {@link #scoreSparse} for dense doc ids.
|
|
|
*/
|
|
|
- Vector scoreDense(T scoreBuilder, int min, int max) throws IOException {
|
|
|
+ Block scoreDense(T scoreBuilder, int min, int max, int positionCount) throws IOException {
|
|
|
if (noMatch) {
|
|
|
- return createNoMatchVector(blockFactory, max - min + 1);
|
|
|
+ return createNoMatchBlock(blockFactory, max - min + 1);
|
|
|
}
|
|
|
if (bulkScorer == null || // The bulkScorer wasn't initialized
|
|
|
Thread.currentThread() != bulkScorerThread // The bulkScorer was initialized on a different thread
|
|
@@ -258,7 +257,7 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
bulkScorer = weight.bulkScorer(ctx);
|
|
|
if (bulkScorer == null) {
|
|
|
noMatch = true;
|
|
|
- return createNoMatchVector(blockFactory, max - min + 1);
|
|
|
+ return createNoMatchBlock(blockFactory, positionCount);
|
|
|
}
|
|
|
}
|
|
|
try (
|
|
@@ -266,11 +265,14 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
min,
|
|
|
max,
|
|
|
scoreBuilder,
|
|
|
+ ctx,
|
|
|
LuceneQueryEvaluator.this::appendNoMatch,
|
|
|
- LuceneQueryEvaluator.this::appendMatch
|
|
|
+ LuceneQueryEvaluator.this::appendMatch,
|
|
|
+ weight.getQuery()
|
|
|
)
|
|
|
) {
|
|
|
bulkScorer.score(collector, ctx.reader().getLiveDocs(), min, max + 1);
|
|
|
+ collector.finish();
|
|
|
return collector.build();
|
|
|
}
|
|
|
}
|
|
@@ -279,10 +281,10 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
* Score a vector of doc ids using {@link Scorer}. If you have a dense range of
|
|
|
* doc ids it'd be faster to use {@link #scoreDense}.
|
|
|
*/
|
|
|
- Vector scoreSparse(T scoreBuilder, IntVector docs) throws IOException {
|
|
|
+ Block scoreSparse(T scoreBuilder, IntVector docs) throws IOException {
|
|
|
initScorer(docs.getInt(0));
|
|
|
if (noMatch) {
|
|
|
- return createNoMatchVector(blockFactory, docs.getPositionCount());
|
|
|
+ return createNoMatchBlock(blockFactory, docs.getPositionCount());
|
|
|
}
|
|
|
for (int i = 0; i < docs.getPositionCount(); i++) {
|
|
|
scoreSingleDocWithScorer(scoreBuilder, docs.getInt(i));
|
|
@@ -326,11 +328,13 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
* doc ids are sent to {@link LeafCollector#collect(int)} in ascending order
|
|
|
* which isn't documented, but @jpountz swears is true.
|
|
|
*/
|
|
|
- static class DenseCollector<U extends Vector.Builder> implements LeafCollector, Releasable {
|
|
|
+ static class DenseCollector<U extends Block.Builder> implements LeafCollector, Releasable {
|
|
|
private final U scoreBuilder;
|
|
|
private final int max;
|
|
|
+ private final LeafReaderContext leafReaderContext;
|
|
|
private final Consumer<U> appendNoMatch;
|
|
|
private final CheckedBiConsumer<U, Scorable, IOException> appendMatch;
|
|
|
+ private final Query query;
|
|
|
|
|
|
private Scorable scorer;
|
|
|
int next;
|
|
@@ -339,14 +343,18 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
int min,
|
|
|
int max,
|
|
|
U scoreBuilder,
|
|
|
+ LeafReaderContext leafReaderContext,
|
|
|
Consumer<U> appendNoMatch,
|
|
|
- CheckedBiConsumer<U, Scorable, IOException> appendMatch
|
|
|
+ CheckedBiConsumer<U, Scorable, IOException> appendMatch,
|
|
|
+ Query query
|
|
|
) {
|
|
|
this.scoreBuilder = scoreBuilder;
|
|
|
this.max = max;
|
|
|
next = min;
|
|
|
+ this.leafReaderContext = leafReaderContext;
|
|
|
this.appendNoMatch = appendNoMatch;
|
|
|
this.appendMatch = appendMatch;
|
|
|
+ this.query = query;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -362,7 +370,7 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
appendMatch.accept(scoreBuilder, scorer);
|
|
|
}
|
|
|
|
|
|
- public Vector build() {
|
|
|
+ public Block build() {
|
|
|
return scoreBuilder.build();
|
|
|
}
|
|
|
|
|
@@ -387,12 +395,12 @@ public abstract class LuceneQueryEvaluator<T extends Vector.Builder> implements
|
|
|
/**
|
|
|
* Creates a vector where all positions correspond to elements that don't match the query
|
|
|
*/
|
|
|
- protected abstract Vector createNoMatchVector(BlockFactory blockFactory, int size);
|
|
|
+ protected abstract Block createNoMatchBlock(BlockFactory blockFactory, int size);
|
|
|
|
|
|
/**
|
|
|
* Creates the corresponding vector builder to store the results of evaluating the query
|
|
|
*/
|
|
|
- protected abstract T createVectorBuilder(BlockFactory blockFactory, int size);
|
|
|
+ protected abstract T createBlockBuilder(BlockFactory blockFactory, int size);
|
|
|
|
|
|
/**
|
|
|
* Appends a matching result to a builder created by @link createVectorBuilder}
|