You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ju...@apache.org on 2022/09/20 22:51:19 UTC
[lucene] 01/02: LUCENE-10577: Remove LeafReader#searchNearestVectorsExhaustively (#11756)
This is an automated email from the ASF dual-hosted git repository.
julietibs pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/lucene.git
commit eb6657664b2289d7b1d482939bd0f328473674da
Author: Julie Tibshirani <ju...@apache.org>
AuthorDate: Thu Sep 8 12:15:02 2022 -0700
LUCENE-10577: Remove LeafReader#searchNearestVectorsExhaustively (#11756)
This PR removes the recently added function on LeafReader to exhaustively search
through vectors, plus the helper function KnnVectorsReader#searchExhaustively.
Instead it performs the exact search within KnnVectorQuery, using a new helper
class called VectorScorer.
---
.../lucene90/Lucene90HnswVectorsReader.java | 17 ----
.../lucene91/Lucene91HnswVectorsReader.java | 17 ----
.../lucene92/Lucene92HnswVectorsReader.java | 17 ----
.../simpletext/SimpleTextKnnVectorsReader.java | 8 --
.../org/apache/lucene/codecs/KnnVectorsFormat.java | 7 --
.../org/apache/lucene/codecs/KnnVectorsReader.java | 95 -------------------
.../codecs/lucene94/Lucene94HnswVectorsReader.java | 25 -----
.../codecs/perfield/PerFieldKnnVectorsFormat.java | 12 ---
.../lucene/index/BufferingKnnVectorsWriter.java | 12 ---
.../java/org/apache/lucene/index/CodecReader.java | 14 ---
.../apache/lucene/index/DocValuesLeafReader.java | 7 --
.../org/apache/lucene/index/FilterLeafReader.java | 7 --
.../java/org/apache/lucene/index/LeafReader.java | 25 -----
.../apache/lucene/index/ParallelLeafReader.java | 11 ---
.../lucene/index/SlowCodecReaderWrapper.java | 7 --
.../apache/lucene/index/SortingCodecReader.java | 7 --
.../org/apache/lucene/search/KnnVectorQuery.java | 38 +++++++-
.../org/apache/lucene/search/VectorScorer.java | 105 +++++++++++++++++++++
.../lucene/index/TestSegmentToThreadMapping.java | 7 --
.../apache/lucene/search/TestKnnVectorQuery.java | 42 +++++++++
.../org/apache/lucene/search/TestVectorScorer.java | 87 +++++++++++++++++
.../search/highlight/TermVectorLeafReader.java | 7 --
.../apache/lucene/index/memory/MemoryIndex.java | 7 --
.../asserting/AssertingKnnVectorsFormat.java | 13 ---
.../lucene/tests/index/MergeReaderWrapper.java | 7 --
.../org/apache/lucene/tests/search/QueryUtils.java | 6 --
26 files changed, 270 insertions(+), 337 deletions(-)
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90HnswVectorsReader.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90HnswVectorsReader.java
index cf5b65b8d00..12cca5af7d1 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90HnswVectorsReader.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90HnswVectorsReader.java
@@ -18,7 +18,6 @@
package org.apache.lucene.backward_codecs.lucene90;
import static org.apache.lucene.search.DocIdSetIterator.NO_MORE_DOCS;
-import static org.apache.lucene.search.TopDocsCollector.EMPTY_TOPDOCS;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -36,7 +35,6 @@ import org.apache.lucene.index.RandomAccessVectorValues;
import org.apache.lucene.index.SegmentReadState;
import org.apache.lucene.index.VectorSimilarityFunction;
import org.apache.lucene.index.VectorValues;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TotalHits;
@@ -278,21 +276,6 @@ public final class Lucene90HnswVectorsReader extends KnnVectorsReader {
return new TopDocs(new TotalHits(results.visitedCount(), relation), scoreDocs);
}
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- FieldEntry fieldEntry = fields.get(field);
- if (fieldEntry == null) {
- // The field does not exist or does not index vectors
- return EMPTY_TOPDOCS;
- }
-
- VectorSimilarityFunction similarityFunction = fieldEntry.similarityFunction;
- VectorValues vectorValues = getVectorValues(field);
-
- return exhaustiveSearch(vectorValues, acceptDocs, similarityFunction, target, k);
- }
-
private OffHeapVectorValues getOffHeapVectorValues(FieldEntry fieldEntry) throws IOException {
IndexInput bytesSlice =
vectorData.slice("vector-data", fieldEntry.vectorDataOffset, fieldEntry.vectorDataLength);
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/Lucene91HnswVectorsReader.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/Lucene91HnswVectorsReader.java
index b8892b37f13..2832327082f 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/Lucene91HnswVectorsReader.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/Lucene91HnswVectorsReader.java
@@ -18,7 +18,6 @@
package org.apache.lucene.backward_codecs.lucene91;
import static org.apache.lucene.search.DocIdSetIterator.NO_MORE_DOCS;
-import static org.apache.lucene.search.TopDocsCollector.EMPTY_TOPDOCS;
import java.io.IOException;
import java.nio.ByteBuffer;
@@ -37,7 +36,6 @@ import org.apache.lucene.index.SegmentReadState;
import org.apache.lucene.index.VectorEncoding;
import org.apache.lucene.index.VectorSimilarityFunction;
import org.apache.lucene.index.VectorValues;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TotalHits;
@@ -268,21 +266,6 @@ public final class Lucene91HnswVectorsReader extends KnnVectorsReader {
return new TopDocs(new TotalHits(results.visitedCount(), relation), scoreDocs);
}
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- FieldEntry fieldEntry = fields.get(field);
- if (fieldEntry == null) {
- // The field does not exist or does not index vectors
- return EMPTY_TOPDOCS;
- }
-
- VectorSimilarityFunction similarityFunction = fieldEntry.similarityFunction;
- VectorValues vectorValues = getVectorValues(field);
-
- return exhaustiveSearch(vectorValues, acceptDocs, similarityFunction, target, k);
- }
-
private OffHeapVectorValues getOffHeapVectorValues(FieldEntry fieldEntry) throws IOException {
IndexInput bytesSlice =
vectorData.slice("vector-data", fieldEntry.vectorDataOffset, fieldEntry.vectorDataLength);
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/Lucene92HnswVectorsReader.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/Lucene92HnswVectorsReader.java
index 8e326464861..32709c47450 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/Lucene92HnswVectorsReader.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/Lucene92HnswVectorsReader.java
@@ -18,7 +18,6 @@
package org.apache.lucene.backward_codecs.lucene92;
import static org.apache.lucene.search.DocIdSetIterator.NO_MORE_DOCS;
-import static org.apache.lucene.search.TopDocsCollector.EMPTY_TOPDOCS;
import java.io.IOException;
import java.util.Arrays;
@@ -34,7 +33,6 @@ import org.apache.lucene.index.SegmentReadState;
import org.apache.lucene.index.VectorEncoding;
import org.apache.lucene.index.VectorSimilarityFunction;
import org.apache.lucene.index.VectorValues;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TotalHits;
@@ -262,21 +260,6 @@ public final class Lucene92HnswVectorsReader extends KnnVectorsReader {
return new TopDocs(new TotalHits(results.visitedCount(), relation), scoreDocs);
}
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- FieldEntry fieldEntry = fields.get(field);
- if (fieldEntry == null) {
- // The field does not exist or does not index vectors
- return EMPTY_TOPDOCS;
- }
-
- VectorSimilarityFunction similarityFunction = fieldEntry.similarityFunction;
- VectorValues vectorValues = getVectorValues(field);
-
- return exhaustiveSearch(vectorValues, acceptDocs, similarityFunction, target, k);
- }
-
/** Get knn graph values; used for testing */
public HnswGraph getGraph(String field) throws IOException {
FieldInfo info = fieldInfos.fieldInfo(field);
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextKnnVectorsReader.java b/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextKnnVectorsReader.java
index 10700f5de6f..060f3decb75 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextKnnVectorsReader.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/simpletext/SimpleTextKnnVectorsReader.java
@@ -183,14 +183,6 @@ public class SimpleTextKnnVectorsReader extends KnnVectorsReader {
return new TopDocs(new TotalHits(numVisited, relation), topScoreDocs);
}
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- FieldInfo info = readState.fieldInfos.fieldInfo(field);
- VectorSimilarityFunction vectorSimilarity = info.getVectorSimilarityFunction();
- return exhaustiveSearch(getVectorValues(field), acceptDocs, vectorSimilarity, target, k);
- }
-
@Override
public void checkIntegrity() throws IOException {
IndexInput clone = dataIn.clone();
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/KnnVectorsFormat.java b/lucene/core/src/java/org/apache/lucene/codecs/KnnVectorsFormat.java
index 68100b88d15..945b213b034 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/KnnVectorsFormat.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/KnnVectorsFormat.java
@@ -21,7 +21,6 @@ import java.io.IOException;
import org.apache.lucene.index.SegmentReadState;
import org.apache.lucene.index.SegmentWriteState;
import org.apache.lucene.index.VectorValues;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TopDocsCollector;
import org.apache.lucene.util.Bits;
@@ -105,12 +104,6 @@ public abstract class KnnVectorsFormat implements NamedSPILoader.NamedSPI {
return TopDocsCollector.EMPTY_TOPDOCS;
}
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) {
- return TopDocsCollector.EMPTY_TOPDOCS;
- }
-
@Override
public void close() {}
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/KnnVectorsReader.java b/lucene/core/src/java/org/apache/lucene/codecs/KnnVectorsReader.java
index 5ae1552facd..711e5e59c19 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/KnnVectorsReader.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/KnnVectorsReader.java
@@ -20,16 +20,12 @@ package org.apache.lucene.codecs;
import java.io.Closeable;
import java.io.IOException;
import org.apache.lucene.index.FieldInfo;
-import org.apache.lucene.index.VectorSimilarityFunction;
import org.apache.lucene.index.VectorValues;
-import org.apache.lucene.search.DocIdSetIterator;
-import org.apache.lucene.search.HitQueue;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TotalHits;
import org.apache.lucene.util.Accountable;
import org.apache.lucene.util.Bits;
-import org.apache.lucene.util.BytesRef;
/** Reads vectors from an index. */
public abstract class KnnVectorsReader implements Closeable, Accountable {
@@ -84,34 +80,6 @@ public abstract class KnnVectorsReader implements Closeable, Accountable {
public abstract TopDocs search(
String field, float[] target, int k, Bits acceptDocs, int visitedLimit) throws IOException;
- /**
- * Return the k nearest neighbor documents as determined by comparison of their vector values for
- * this field, to the given vector, by the field's similarity function. The score of each document
- * is derived from the vector similarity in a way that ensures scores are positive and that a
- * larger score corresponds to a higher ranking.
- *
- * <p>The search is exact, guaranteeing the true k closest neighbors will be returned. Typically
- * this requires an exhaustive scan of the entire index. It is intended to be used when the number
- * of potential matches is limited.
- *
- * <p>The returned {@link TopDocs} will contain a {@link ScoreDoc} for each nearest neighbor, in
- * order of their similarity to the query vector (decreasing scores). The {@link TotalHits}
- * contains the number of documents visited during the search. If the search stopped early because
- * it hit {@code visitedLimit}, it is indicated through the relation {@code
- * TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO}.
- *
- * <p>The behavior is undefined if the given field doesn't have KNN vectors enabled on its {@link
- * FieldInfo}. The return value is never {@code null}.
- *
- * @param field the vector field to search
- * @param target the vector-valued query
- * @param k the number of docs to return
- * @param acceptDocs {@link DocIdSetIterator} that represents the allowed documents to match.
- * @return the k nearest neighbor documents, along with their (similarity-specific) scores.
- */
- public abstract TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException;
-
/**
* Returns an instance optimized for merging. This instance may only be consumed in the thread
* that called {@link #getMergeInstance()}.
@@ -121,67 +89,4 @@ public abstract class KnnVectorsReader implements Closeable, Accountable {
public KnnVectorsReader getMergeInstance() {
return this;
}
-
- /** {@link #searchExhaustively} */
- protected static TopDocs exhaustiveSearch(
- VectorValues vectorValues,
- DocIdSetIterator acceptDocs,
- VectorSimilarityFunction similarityFunction,
- float[] target,
- int k)
- throws IOException {
- HitQueue queue = new HitQueue(k, true);
- ScoreDoc topDoc = queue.top();
- int doc;
- while ((doc = acceptDocs.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
- int vectorDoc = vectorValues.advance(doc);
- assert vectorDoc == doc;
- float score = similarityFunction.compare(vectorValues.vectorValue(), target);
- if (score >= topDoc.score) {
- topDoc.score = score;
- topDoc.doc = doc;
- topDoc = queue.updateTop();
- }
- }
- return topDocsFromHitQueue(queue, acceptDocs.cost());
- }
-
- /** {@link #searchExhaustively} */
- protected static TopDocs exhaustiveSearch(
- VectorValues vectorValues,
- DocIdSetIterator acceptDocs,
- VectorSimilarityFunction similarityFunction,
- BytesRef target,
- int k)
- throws IOException {
- HitQueue queue = new HitQueue(k, true);
- ScoreDoc topDoc = queue.top();
- int doc;
- while ((doc = acceptDocs.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
- int vectorDoc = vectorValues.advance(doc);
- assert vectorDoc == doc;
- float score = similarityFunction.compare(vectorValues.binaryValue(), target);
- if (score >= topDoc.score) {
- topDoc.score = score;
- topDoc.doc = doc;
- topDoc = queue.updateTop();
- }
- }
- return topDocsFromHitQueue(queue, acceptDocs.cost());
- }
-
- private static TopDocs topDocsFromHitQueue(HitQueue queue, long numHits) {
- // Remove any remaining sentinel values
- while (queue.size() > 0 && queue.top().score < 0) {
- queue.pop();
- }
-
- ScoreDoc[] topScoreDocs = new ScoreDoc[queue.size()];
- for (int i = topScoreDocs.length - 1; i >= 0; i--) {
- topScoreDocs[i] = queue.pop();
- }
-
- TotalHits totalHits = new TotalHits(numHits, TotalHits.Relation.EQUAL_TO);
- return new TopDocs(totalHits, topScoreDocs);
- }
}
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene94/Lucene94HnswVectorsReader.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene94/Lucene94HnswVectorsReader.java
index 2b7f01cc6a8..1d02d818f8b 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene94/Lucene94HnswVectorsReader.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene94/Lucene94HnswVectorsReader.java
@@ -18,8 +18,6 @@
package org.apache.lucene.codecs.lucene94;
import static org.apache.lucene.search.DocIdSetIterator.NO_MORE_DOCS;
-import static org.apache.lucene.search.TopDocsCollector.EMPTY_TOPDOCS;
-import static org.apache.lucene.util.VectorUtil.toBytesRef;
import java.io.IOException;
import java.util.Arrays;
@@ -35,7 +33,6 @@ import org.apache.lucene.index.SegmentReadState;
import org.apache.lucene.index.VectorEncoding;
import org.apache.lucene.index.VectorSimilarityFunction;
import org.apache.lucene.index.VectorValues;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TotalHits;
@@ -289,28 +286,6 @@ public final class Lucene94HnswVectorsReader extends KnnVectorsReader {
return new TopDocs(new TotalHits(results.visitedCount(), relation), scoreDocs);
}
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- FieldEntry fieldEntry = fields.get(field);
- if (fieldEntry == null) {
- // The field does not exist or does not index vectors
- return EMPTY_TOPDOCS;
- }
-
- VectorSimilarityFunction similarityFunction = fieldEntry.similarityFunction;
- VectorValues vectorValues = getVectorValues(field);
-
- switch (fieldEntry.vectorEncoding) {
- case BYTE:
- return exhaustiveSearch(
- vectorValues, acceptDocs, similarityFunction, toBytesRef(target), k);
- default:
- case FLOAT32:
- return exhaustiveSearch(vectorValues, acceptDocs, similarityFunction, target, k);
- }
- }
-
/** Get knn graph values; used for testing */
public HnswGraph getGraph(String field) throws IOException {
FieldInfo info = fieldInfos.fieldInfo(field);
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/perfield/PerFieldKnnVectorsFormat.java b/lucene/core/src/java/org/apache/lucene/codecs/perfield/PerFieldKnnVectorsFormat.java
index d0a46cdb8c0..e30d24fbc8e 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/perfield/PerFieldKnnVectorsFormat.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/perfield/PerFieldKnnVectorsFormat.java
@@ -33,7 +33,6 @@ import org.apache.lucene.index.SegmentReadState;
import org.apache.lucene.index.SegmentWriteState;
import org.apache.lucene.index.Sorter;
import org.apache.lucene.index.VectorValues;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TotalHits;
@@ -268,17 +267,6 @@ public abstract class PerFieldKnnVectorsFormat extends KnnVectorsFormat {
}
}
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- KnnVectorsReader knnVectorsReader = fields.get(field);
- if (knnVectorsReader == null) {
- return new TopDocs(new TotalHits(0, TotalHits.Relation.EQUAL_TO), new ScoreDoc[0]);
- } else {
- return knnVectorsReader.searchExhaustively(field, target, k, acceptDocs);
- }
- }
-
@Override
public void close() throws IOException {
IOUtils.close(fields.values());
diff --git a/lucene/core/src/java/org/apache/lucene/index/BufferingKnnVectorsWriter.java b/lucene/core/src/java/org/apache/lucene/index/BufferingKnnVectorsWriter.java
index f8bb43c342e..28373a9c6d7 100644
--- a/lucene/core/src/java/org/apache/lucene/index/BufferingKnnVectorsWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/index/BufferingKnnVectorsWriter.java
@@ -88,12 +88,6 @@ public abstract class BufferingKnnVectorsWriter extends KnnVectorsWriter {
String field, float[] target, int k, Bits acceptDocs, int visitedLimit) {
throw new UnsupportedOperationException();
}
-
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) {
- throw new UnsupportedOperationException();
- }
};
writeField(fieldData.fieldInfo, knnVectorsReader, maxDoc);
@@ -128,12 +122,6 @@ public abstract class BufferingKnnVectorsWriter extends KnnVectorsWriter {
throw new UnsupportedOperationException();
}
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) {
- throw new UnsupportedOperationException();
- }
-
@Override
public VectorValues getVectorValues(String field) throws IOException {
return MergedVectorValues.mergeVectorValues(fieldInfo, mergeState);
diff --git a/lucene/core/src/java/org/apache/lucene/index/CodecReader.java b/lucene/core/src/java/org/apache/lucene/index/CodecReader.java
index 99c7ebb0b91..5867357a164 100644
--- a/lucene/core/src/java/org/apache/lucene/index/CodecReader.java
+++ b/lucene/core/src/java/org/apache/lucene/index/CodecReader.java
@@ -25,7 +25,6 @@ import org.apache.lucene.codecs.NormsProducer;
import org.apache.lucene.codecs.PointsReader;
import org.apache.lucene.codecs.StoredFieldsReader;
import org.apache.lucene.codecs.TermVectorsReader;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.util.Bits;
@@ -236,19 +235,6 @@ public abstract class CodecReader extends LeafReader {
return getVectorReader().search(field, target, k, acceptDocs, visitedLimit);
}
- @Override
- public final TopDocs searchNearestVectorsExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- ensureOpen();
- FieldInfo fi = getFieldInfos().fieldInfo(field);
- if (fi == null || fi.getVectorDimension() == 0) {
- // Field does not exist or does not index vectors
- return null;
- }
-
- return getVectorReader().searchExhaustively(field, target, k, acceptDocs);
- }
-
@Override
protected void doClose() throws IOException {}
diff --git a/lucene/core/src/java/org/apache/lucene/index/DocValuesLeafReader.java b/lucene/core/src/java/org/apache/lucene/index/DocValuesLeafReader.java
index 0aa77ea495f..99853d9abd8 100644
--- a/lucene/core/src/java/org/apache/lucene/index/DocValuesLeafReader.java
+++ b/lucene/core/src/java/org/apache/lucene/index/DocValuesLeafReader.java
@@ -18,7 +18,6 @@
package org.apache.lucene.index;
import java.io.IOException;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.util.Bits;
@@ -59,12 +58,6 @@ abstract class DocValuesLeafReader extends LeafReader {
throw new UnsupportedOperationException();
}
- @Override
- public TopDocs searchNearestVectorsExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- throw new UnsupportedOperationException();
- }
-
@Override
public final void checkIntegrity() throws IOException {
throw new UnsupportedOperationException();
diff --git a/lucene/core/src/java/org/apache/lucene/index/FilterLeafReader.java b/lucene/core/src/java/org/apache/lucene/index/FilterLeafReader.java
index 731733167c2..8114bf3e3d5 100644
--- a/lucene/core/src/java/org/apache/lucene/index/FilterLeafReader.java
+++ b/lucene/core/src/java/org/apache/lucene/index/FilterLeafReader.java
@@ -18,7 +18,6 @@ package org.apache.lucene.index;
import java.io.IOException;
import java.util.Iterator;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.util.AttributeSource;
import org.apache.lucene.util.Bits;
@@ -358,12 +357,6 @@ public abstract class FilterLeafReader extends LeafReader {
return in.searchNearestVectors(field, target, k, acceptDocs, visitedLimit);
}
- @Override
- public TopDocs searchNearestVectorsExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- return in.searchNearestVectorsExhaustively(field, target, k, acceptDocs);
- }
-
@Override
public Fields getTermVectors(int docID) throws IOException {
ensureOpen();
diff --git a/lucene/core/src/java/org/apache/lucene/index/LeafReader.java b/lucene/core/src/java/org/apache/lucene/index/LeafReader.java
index 2dd3a03e8b2..017c085b540 100644
--- a/lucene/core/src/java/org/apache/lucene/index/LeafReader.java
+++ b/lucene/core/src/java/org/apache/lucene/index/LeafReader.java
@@ -17,7 +17,6 @@
package org.apache.lucene.index;
import java.io.IOException;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TotalHits;
@@ -236,30 +235,6 @@ public abstract class LeafReader extends IndexReader {
public abstract TopDocs searchNearestVectors(
String field, float[] target, int k, Bits acceptDocs, int visitedLimit) throws IOException;
- /**
- * Return the k nearest neighbor documents as determined by comparison of their vector values for
- * this field, to the given vector, by the field's similarity function. The score of each document
- * is derived from the vector similarity in a way that ensures scores are positive and that a
- * larger score corresponds to a higher ranking.
- *
- * <p>The search is exact, meaning the results are guaranteed to be the true k closest neighbors.
- * This typically requires an exhaustive scan of all candidate documents.
- *
- * <p>The returned {@link TopDocs} will contain a {@link ScoreDoc} for each nearest neighbor,
- * sorted in order of their similarity to the query vector (decreasing scores). The {@link
- * TotalHits} contains the number of documents visited during the search.
- *
- * @param field the vector field to search
- * @param target the vector-valued query
- * @param k the number of docs to return
- * @param acceptDocs {@link DocIdSetIterator} that represents the allowed documents to match, or
- * {@code null} if they are all allowed to match.
- * @return the k nearest neighbor documents, along with their (searchStrategy-specific) scores.
- * @lucene.experimental
- */
- public abstract TopDocs searchNearestVectorsExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException;
-
/**
* Get the {@link FieldInfos} describing all fields in this reader.
*
diff --git a/lucene/core/src/java/org/apache/lucene/index/ParallelLeafReader.java b/lucene/core/src/java/org/apache/lucene/index/ParallelLeafReader.java
index 509b658d33b..62fb344607a 100644
--- a/lucene/core/src/java/org/apache/lucene/index/ParallelLeafReader.java
+++ b/lucene/core/src/java/org/apache/lucene/index/ParallelLeafReader.java
@@ -26,7 +26,6 @@ import java.util.Objects;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.util.Bits;
@@ -412,16 +411,6 @@ public class ParallelLeafReader extends LeafReader {
: reader.searchNearestVectors(fieldName, target, k, acceptDocs, visitedLimit);
}
- @Override
- public TopDocs searchNearestVectorsExhaustively(
- String fieldName, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- ensureOpen();
- LeafReader reader = fieldToReader.get(fieldName);
- return reader == null
- ? null
- : reader.searchNearestVectorsExhaustively(fieldName, target, k, acceptDocs);
- }
-
@Override
public void checkIntegrity() throws IOException {
ensureOpen();
diff --git a/lucene/core/src/java/org/apache/lucene/index/SlowCodecReaderWrapper.java b/lucene/core/src/java/org/apache/lucene/index/SlowCodecReaderWrapper.java
index 89d8ca611b9..034a91b960c 100644
--- a/lucene/core/src/java/org/apache/lucene/index/SlowCodecReaderWrapper.java
+++ b/lucene/core/src/java/org/apache/lucene/index/SlowCodecReaderWrapper.java
@@ -27,7 +27,6 @@ import org.apache.lucene.codecs.NormsProducer;
import org.apache.lucene.codecs.PointsReader;
import org.apache.lucene.codecs.StoredFieldsReader;
import org.apache.lucene.codecs.TermVectorsReader;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.util.Bits;
@@ -173,12 +172,6 @@ public final class SlowCodecReaderWrapper {
return reader.searchNearestVectors(field, target, k, acceptDocs, visitedLimit);
}
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- return reader.searchNearestVectorsExhaustively(field, target, k, acceptDocs);
- }
-
@Override
public void checkIntegrity() {
// We already checkIntegrity the entire reader up front
diff --git a/lucene/core/src/java/org/apache/lucene/index/SortingCodecReader.java b/lucene/core/src/java/org/apache/lucene/index/SortingCodecReader.java
index 8a1b9eb0d34..7fb91bf6621 100644
--- a/lucene/core/src/java/org/apache/lucene/index/SortingCodecReader.java
+++ b/lucene/core/src/java/org/apache/lucene/index/SortingCodecReader.java
@@ -31,7 +31,6 @@ import org.apache.lucene.codecs.NormsProducer;
import org.apache.lucene.codecs.PointsReader;
import org.apache.lucene.codecs.StoredFieldsReader;
import org.apache.lucene.codecs.TermVectorsReader;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TopDocs;
@@ -390,12 +389,6 @@ public final class SortingCodecReader extends FilterCodecReader {
throw new UnsupportedOperationException();
}
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) {
- throw new UnsupportedOperationException();
- }
-
@Override
public void close() throws IOException {
delegate.close();
diff --git a/lucene/core/src/java/org/apache/lucene/search/KnnVectorQuery.java b/lucene/core/src/java/org/apache/lucene/search/KnnVectorQuery.java
index f0d547c0f5e..883e2b416ea 100644
--- a/lucene/core/src/java/org/apache/lucene/search/KnnVectorQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/KnnVectorQuery.java
@@ -24,6 +24,7 @@ import java.util.Comparator;
import java.util.Objects;
import org.apache.lucene.codecs.KnnVectorsReader;
import org.apache.lucene.document.KnnVectorField;
+import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.util.BitSet;
@@ -175,9 +176,42 @@ public class KnnVectorQuery extends Query {
}
// We allow this to be overridden so that tests can check what search strategy is used
- protected TopDocs exactSearch(LeafReaderContext context, DocIdSetIterator acceptDocs)
+ protected TopDocs exactSearch(LeafReaderContext context, DocIdSetIterator acceptIterator)
throws IOException {
- return context.reader().searchNearestVectorsExhaustively(field, target, k, acceptDocs);
+ FieldInfo fi = context.reader().getFieldInfos().fieldInfo(field);
+ if (fi == null || fi.getVectorDimension() == 0) {
+ // The field does not exist or does not index vectors
+ return NO_RESULTS;
+ }
+
+ VectorScorer vectorScorer = VectorScorer.create(context, fi, target);
+ HitQueue queue = new HitQueue(k, true);
+ ScoreDoc topDoc = queue.top();
+ int doc;
+ while ((doc = acceptIterator.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {
+ boolean advanced = vectorScorer.advanceExact(doc);
+ assert advanced;
+
+ float score = vectorScorer.score();
+ if (score > topDoc.score) {
+ topDoc.score = score;
+ topDoc.doc = doc;
+ topDoc = queue.updateTop();
+ }
+ }
+
+ // Remove any remaining sentinel values
+ while (queue.size() > 0 && queue.top().score < 0) {
+ queue.pop();
+ }
+
+ ScoreDoc[] topScoreDocs = new ScoreDoc[queue.size()];
+ for (int i = topScoreDocs.length - 1; i >= 0; i--) {
+ topScoreDocs[i] = queue.pop();
+ }
+
+ TotalHits totalHits = new TotalHits(acceptIterator.cost(), TotalHits.Relation.EQUAL_TO);
+ return new TopDocs(totalHits, topScoreDocs);
}
private Query createRewrittenQuery(IndexReader reader, TopDocs topK) {
diff --git a/lucene/core/src/java/org/apache/lucene/search/VectorScorer.java b/lucene/core/src/java/org/apache/lucene/search/VectorScorer.java
new file mode 100644
index 00000000000..6a8850c69ec
--- /dev/null
+++ b/lucene/core/src/java/org/apache/lucene/search/VectorScorer.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.search;
+
+import java.io.IOException;
+import org.apache.lucene.index.FieldInfo;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.VectorSimilarityFunction;
+import org.apache.lucene.index.VectorValues;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.VectorUtil;
+
+/**
+ * Computes the similarity score between a given query vector and different document vectors. This
+ * is primarily used by {@link org.apache.lucene.search.KnnVectorQuery} to run an exact, exhaustive
+ * search over the vectors.
+ */
+abstract class VectorScorer {
+ protected final VectorValues values;
+ protected final VectorSimilarityFunction similarity;
+
+ /**
+ * Create a new vector scorer instance.
+ *
+ * @param context the reader context
+ * @param fi the FieldInfo for the field containing document vectors
+ * @param query the query vector to compute the similarity for
+ */
+ static VectorScorer create(LeafReaderContext context, FieldInfo fi, float[] query)
+ throws IOException {
+ VectorValues values = context.reader().getVectorValues(fi.name);
+ VectorSimilarityFunction similarity = fi.getVectorSimilarityFunction();
+ switch (fi.getVectorEncoding()) {
+ case BYTE:
+ return new ByteVectorScorer(values, query, similarity);
+ default:
+ case FLOAT32:
+ return new FloatVectorScorer(values, query, similarity);
+ }
+ }
+
+ VectorScorer(VectorValues values, VectorSimilarityFunction similarity) {
+ this.values = values;
+ this.similarity = similarity;
+ }
+
+ /**
+ * Advance the instance to the given document ID and return true if there is a value for that
+ * document.
+ */
+ public boolean advanceExact(int doc) throws IOException {
+ int vectorDoc = values.docID();
+ if (vectorDoc < doc) {
+ vectorDoc = values.advance(doc);
+ }
+ return vectorDoc == doc;
+ }
+
+ /** Compute the similarity score for the current document. */
+ abstract float score() throws IOException;
+
+ private static class ByteVectorScorer extends VectorScorer {
+ private final BytesRef query;
+
+ protected ByteVectorScorer(
+ VectorValues values, float[] query, VectorSimilarityFunction similarity) {
+ super(values, similarity);
+ this.query = VectorUtil.toBytesRef(query);
+ }
+
+ @Override
+ public float score() throws IOException {
+ return similarity.compare(query, values.binaryValue());
+ }
+ }
+
+ private static class FloatVectorScorer extends VectorScorer {
+ private final float[] query;
+
+ protected FloatVectorScorer(
+ VectorValues values, float[] query, VectorSimilarityFunction similarity) {
+ super(values, similarity);
+ this.query = query;
+ }
+
+ @Override
+ public float score() throws IOException {
+ return similarity.compare(query, values.vectorValue());
+ }
+ }
+}
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestSegmentToThreadMapping.java b/lucene/core/src/test/org/apache/lucene/index/TestSegmentToThreadMapping.java
index ab22d6678a1..8eaee902c0e 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestSegmentToThreadMapping.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestSegmentToThreadMapping.java
@@ -25,7 +25,6 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.lucene.document.Document;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
@@ -118,12 +117,6 @@ public class TestSegmentToThreadMapping extends LuceneTestCase {
return null;
}
- @Override
- public TopDocs searchNearestVectorsExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) {
- return null;
- }
-
@Override
protected void doClose() {}
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestKnnVectorQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestKnnVectorQuery.java
index c079b6d4fc3..df7f03f1901 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestKnnVectorQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestKnnVectorQuery.java
@@ -631,6 +631,48 @@ public class TestKnnVectorQuery extends LuceneTestCase {
}
}
+ /** Tests filtering when all vectors have the same score. */
+ public void testFilterWithSameScore() throws IOException {
+ int numDocs = 100;
+ int dimension = atLeast(5);
+ try (Directory d = newDirectory()) {
+ // Always use the default kNN format to have predictable behavior around when it hits
+ // visitedLimit. This is fine since the test targets KnnVectorQuery logic, not the kNN format
+ // implementation.
+ IndexWriterConfig iwc = new IndexWriterConfig().setCodec(TestUtil.getDefaultCodec());
+ IndexWriter w = new IndexWriter(d, iwc);
+ float[] vector = randomVector(dimension);
+ for (int i = 0; i < numDocs; i++) {
+ Document doc = new Document();
+ doc.add(new KnnVectorField("field", vector));
+ doc.add(new IntPoint("tag", i));
+ w.addDocument(doc);
+ }
+ w.forceMerge(1);
+ w.close();
+
+ try (DirectoryReader reader = DirectoryReader.open(d)) {
+ IndexSearcher searcher = newSearcher(reader);
+ int lower = random().nextInt(50);
+ int size = 5;
+
+ // Test a restrictive filter, which usually performs exact search
+ Query filter1 = IntPoint.newRangeQuery("tag", lower, lower + 6);
+ TopDocs results =
+ searcher.search(
+ new KnnVectorQuery("field", randomVector(dimension), size, filter1), size);
+ assertEquals(size, results.scoreDocs.length);
+
+ // Test an unrestrictive filter, which usually performs approximate search
+ Query filter2 = IntPoint.newRangeQuery("tag", lower, numDocs);
+ results =
+ searcher.search(
+ new KnnVectorQuery("field", randomVector(dimension), size, filter2), size);
+ assertEquals(size, results.scoreDocs.length);
+ }
+ }
+ }
+
public void testDeletes() throws IOException {
try (Directory dir = newDirectory();
IndexWriter w = new IndexWriter(dir, newIndexWriterConfig())) {
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestVectorScorer.java b/lucene/core/src/test/org/apache/lucene/search/TestVectorScorer.java
new file mode 100644
index 00000000000..979283c7701
--- /dev/null
+++ b/lucene/core/src/test/org/apache/lucene/search/TestVectorScorer.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.search;
+
+import static org.apache.lucene.index.VectorSimilarityFunction.EUCLIDEAN;
+
+import java.io.IOException;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.KnnVectorField;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.FieldInfo;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.VectorEncoding;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.tests.index.RandomIndexWriter;
+import org.apache.lucene.tests.util.LuceneTestCase;
+import org.apache.lucene.util.BytesRef;
+
+public class TestVectorScorer extends LuceneTestCase {
+
+ public void testFindAll() throws IOException {
+ try (Directory indexStore =
+ getIndexStore("field", new float[] {0, 1}, new float[] {1, 2}, new float[] {0, 0});
+ IndexReader reader = DirectoryReader.open(indexStore)) {
+ assert reader.leaves().size() == 1;
+ LeafReaderContext context = reader.leaves().get(0);
+ FieldInfo fieldInfo = context.reader().getFieldInfos().fieldInfo("field");
+ VectorScorer vectorScorer = VectorScorer.create(context, fieldInfo, new float[] {1, 2});
+
+ int numDocs = 0;
+ for (int i = 0; i < reader.maxDoc(); i++) {
+ if (vectorScorer.advanceExact(i)) {
+ numDocs++;
+ }
+ }
+ assertEquals(3, numDocs);
+ }
+ }
+
+ /** Creates a new directory and adds documents with the given vectors as kNN vector fields */
+ private Directory getIndexStore(String field, float[]... contents) throws IOException {
+ Directory indexStore = newDirectory();
+ RandomIndexWriter writer = new RandomIndexWriter(random(), indexStore);
+ VectorEncoding encoding =
+ VectorEncoding.values()[random().nextInt(VectorEncoding.values().length)];
+ for (int i = 0; i < contents.length; ++i) {
+ Document doc = new Document();
+ if (encoding == VectorEncoding.BYTE) {
+ BytesRef v = new BytesRef(new byte[contents[i].length]);
+ for (int j = 0; j < v.length; j++) {
+ v.bytes[j] = (byte) contents[i][j];
+ }
+ doc.add(new KnnVectorField(field, v, EUCLIDEAN));
+ } else {
+ doc.add(new KnnVectorField(field, contents[i]));
+ }
+ doc.add(new StringField("id", "id" + i, Field.Store.YES));
+ writer.addDocument(doc);
+ }
+ // Add some documents without a vector
+ for (int i = 0; i < 5; i++) {
+ Document doc = new Document();
+ doc.add(new StringField("other", "value", Field.Store.NO));
+ writer.addDocument(doc);
+ }
+ writer.forceMerge(1);
+ writer.close();
+ return indexStore;
+ }
+}
diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/TermVectorLeafReader.java b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/TermVectorLeafReader.java
index acf5575129a..71cc8830aad 100644
--- a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/TermVectorLeafReader.java
+++ b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/TermVectorLeafReader.java
@@ -37,7 +37,6 @@ import org.apache.lucene.index.Terms;
import org.apache.lucene.index.VectorEncoding;
import org.apache.lucene.index.VectorSimilarityFunction;
import org.apache.lucene.index.VectorValues;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.Version;
@@ -169,12 +168,6 @@ public class TermVectorLeafReader extends LeafReader {
return null;
}
- @Override
- public TopDocs searchNearestVectorsExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) {
- return null;
- }
-
@Override
public void checkIntegrity() throws IOException {}
diff --git a/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java b/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
index 805d649b86d..9e5d03979fa 100644
--- a/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
+++ b/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
@@ -37,7 +37,6 @@ import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.*;
import org.apache.lucene.search.Collector;
import org.apache.lucene.search.CollectorManager;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Scorable;
@@ -1375,12 +1374,6 @@ public class MemoryIndex {
return null;
}
- @Override
- public TopDocs searchNearestVectorsExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) {
- return null;
- }
-
@Override
public void checkIntegrity() throws IOException {
// no-op
diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/asserting/AssertingKnnVectorsFormat.java b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/asserting/AssertingKnnVectorsFormat.java
index b8edf9fbcc3..4224f66fe6b 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/asserting/AssertingKnnVectorsFormat.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/asserting/AssertingKnnVectorsFormat.java
@@ -29,7 +29,6 @@ import org.apache.lucene.index.SegmentReadState;
import org.apache.lucene.index.SegmentWriteState;
import org.apache.lucene.index.Sorter;
import org.apache.lucene.index.VectorValues;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.tests.util.TestUtil;
import org.apache.lucene.util.Bits;
@@ -132,18 +131,6 @@ public class AssertingKnnVectorsFormat extends KnnVectorsFormat {
return hits;
}
- @Override
- public TopDocs searchExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- FieldInfo fi = fis.fieldInfo(field);
- assert fi != null && fi.getVectorDimension() > 0;
- assert acceptDocs != null;
- TopDocs hits = delegate.searchExhaustively(field, target, k, acceptDocs);
- assert hits != null;
- assert hits.scoreDocs.length <= k;
- return hits;
- }
-
@Override
public void close() throws IOException {
delegate.close();
diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/index/MergeReaderWrapper.java b/lucene/test-framework/src/java/org/apache/lucene/tests/index/MergeReaderWrapper.java
index 6c577eaaf70..36134697e35 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/tests/index/MergeReaderWrapper.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/tests/index/MergeReaderWrapper.java
@@ -40,7 +40,6 @@ import org.apache.lucene.index.SortedSetDocValues;
import org.apache.lucene.index.StoredFieldVisitor;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.VectorValues;
-import org.apache.lucene.search.DocIdSetIterator;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.util.Bits;
@@ -229,12 +228,6 @@ class MergeReaderWrapper extends LeafReader {
return in.searchNearestVectors(field, target, k, acceptDocs, visitedLimit);
}
- @Override
- public TopDocs searchNearestVectorsExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) throws IOException {
- return in.searchNearestVectorsExhaustively(field, target, k, acceptDocs);
- }
-
@Override
public int numDocs() {
return in.numDocs();
diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/search/QueryUtils.java b/lucene/test-framework/src/java/org/apache/lucene/tests/search/QueryUtils.java
index ec15851ce66..413a45db8d8 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/tests/search/QueryUtils.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/tests/search/QueryUtils.java
@@ -233,12 +233,6 @@ public class QueryUtils {
return null;
}
- @Override
- public TopDocs searchNearestVectorsExhaustively(
- String field, float[] target, int k, DocIdSetIterator acceptDocs) {
- return null;
- }
-
@Override
public FieldInfos getFieldInfos() {
return FieldInfos.EMPTY;