mirror of https://github.com/apache/lucene.git
LUCENE-10354: Clarify contract of codec APIs with missing/disabled fields. (#583)
This commit is contained in:
parent
7fdba36941
commit
c8651afde7
|
@ -19,6 +19,7 @@ package org.apache.lucene.codecs;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.apache.lucene.index.BinaryDocValues;
|
import org.apache.lucene.index.BinaryDocValues;
|
||||||
|
import org.apache.lucene.index.DocValuesType;
|
||||||
import org.apache.lucene.index.FieldInfo;
|
import org.apache.lucene.index.FieldInfo;
|
||||||
import org.apache.lucene.index.NumericDocValues;
|
import org.apache.lucene.index.NumericDocValues;
|
||||||
import org.apache.lucene.index.SortedDocValues;
|
import org.apache.lucene.index.SortedDocValues;
|
||||||
|
@ -37,31 +38,38 @@ public abstract class DocValuesProducer implements Closeable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link NumericDocValues} for this field. The returned instance need not be thread-safe:
|
* Returns {@link NumericDocValues} for this field. The returned instance need not be thread-safe:
|
||||||
* it will only be used by a single thread.
|
* it will only be used by a single thread. The behavior is undefined if the doc values type of
|
||||||
|
* the given field is not {@link DocValuesType#NUMERIC}. The return value is never {@code null}.
|
||||||
*/
|
*/
|
||||||
public abstract NumericDocValues getNumeric(FieldInfo field) throws IOException;
|
public abstract NumericDocValues getNumeric(FieldInfo field) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link BinaryDocValues} for this field. The returned instance need not be thread-safe:
|
* Returns {@link BinaryDocValues} for this field. The returned instance need not be thread-safe:
|
||||||
* it will only be used by a single thread.
|
* it will only be used by a single thread. The behavior is undefined if the doc values type of
|
||||||
|
* the given field is not {@link DocValuesType#BINARY}. The return value is never {@code null}.
|
||||||
*/
|
*/
|
||||||
public abstract BinaryDocValues getBinary(FieldInfo field) throws IOException;
|
public abstract BinaryDocValues getBinary(FieldInfo field) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link SortedDocValues} for this field. The returned instance need not be thread-safe:
|
* Returns {@link SortedDocValues} for this field. The returned instance need not be thread-safe:
|
||||||
* it will only be used by a single thread.
|
* it will only be used by a single thread. The behavior is undefined if the doc values type of
|
||||||
|
* the given field is not {@link DocValuesType#SORTED}. The return value is never {@code null}.
|
||||||
*/
|
*/
|
||||||
public abstract SortedDocValues getSorted(FieldInfo field) throws IOException;
|
public abstract SortedDocValues getSorted(FieldInfo field) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link SortedNumericDocValues} for this field. The returned instance need not be
|
* Returns {@link SortedNumericDocValues} for this field. The returned instance need not be
|
||||||
* thread-safe: it will only be used by a single thread.
|
* thread-safe: it will only be used by a single thread. The behavior is undefined if the doc
|
||||||
|
* values type of the given field is not {@link DocValuesType#SORTED_NUMERIC}. The return value is
|
||||||
|
* never {@code null}.
|
||||||
*/
|
*/
|
||||||
public abstract SortedNumericDocValues getSortedNumeric(FieldInfo field) throws IOException;
|
public abstract SortedNumericDocValues getSortedNumeric(FieldInfo field) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link SortedSetDocValues} for this field. The returned instance need not be
|
* Returns {@link SortedSetDocValues} for this field. The returned instance need not be
|
||||||
* thread-safe: it will only be used by a single thread.
|
* thread-safe: it will only be used by a single thread. The behavior is undefined if the doc
|
||||||
|
* values type of the given field is not {@link DocValuesType#SORTED_SET}. The return value is
|
||||||
|
* never {@code null}.
|
||||||
*/
|
*/
|
||||||
public abstract SortedSetDocValues getSortedSet(FieldInfo field) throws IOException;
|
public abstract SortedSetDocValues getSortedSet(FieldInfo field) throws IOException;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.lucene.codecs;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.apache.lucene.index.FieldInfo;
|
||||||
import org.apache.lucene.index.VectorValues;
|
import org.apache.lucene.index.VectorValues;
|
||||||
import org.apache.lucene.search.TopDocs;
|
import org.apache.lucene.search.TopDocs;
|
||||||
import org.apache.lucene.util.Accountable;
|
import org.apache.lucene.util.Accountable;
|
||||||
|
@ -40,7 +41,11 @@ public abstract class KnnVectorsReader implements Closeable, Accountable {
|
||||||
*/
|
*/
|
||||||
public abstract void checkIntegrity() throws IOException;
|
public abstract void checkIntegrity() throws IOException;
|
||||||
|
|
||||||
/** Returns the {@link VectorValues} for the given {@code field} */
|
/**
|
||||||
|
* Returns the {@link VectorValues} for the given {@code field}. 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}.
|
||||||
|
*/
|
||||||
public abstract VectorValues getVectorValues(String field) throws IOException;
|
public abstract VectorValues getVectorValues(String field) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,6 +58,9 @@ public abstract class KnnVectorsReader implements Closeable, Accountable {
|
||||||
* true k closest neighbors. For large values of k (for example when k is close to the total
|
* true k closest neighbors. For large values of k (for example when k is close to the total
|
||||||
* number of documents), the search may also retrieve fewer than k documents.
|
* number of documents), the search may also retrieve fewer than k documents.
|
||||||
*
|
*
|
||||||
|
* <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 field the vector field to search
|
||||||
* @param target the vector-valued query
|
* @param target the vector-valued query
|
||||||
* @param k the number of docs to return
|
* @param k the number of docs to return
|
||||||
|
|
|
@ -33,7 +33,8 @@ public abstract class NormsProducer implements Closeable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link NumericDocValues} for this field. The returned instance need not be thread-safe:
|
* Returns {@link NumericDocValues} for this field. The returned instance need not be thread-safe:
|
||||||
* it will only be used by a single thread.
|
* it will only be used by a single thread. The behavior is undefined if the given field doesn't
|
||||||
|
* have norms enabled on its {@link FieldInfo}. The return value is never {@code null}.
|
||||||
*/
|
*/
|
||||||
public abstract NumericDocValues getNorms(FieldInfo field) throws IOException;
|
public abstract NumericDocValues getNorms(FieldInfo field) throws IOException;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.apache.lucene.codecs;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.apache.lucene.index.FieldInfo;
|
||||||
import org.apache.lucene.index.PointValues;
|
import org.apache.lucene.index.PointValues;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,7 +41,10 @@ public abstract class PointsReader implements Closeable {
|
||||||
*/
|
*/
|
||||||
public abstract void checkIntegrity() throws IOException;
|
public abstract void checkIntegrity() throws IOException;
|
||||||
|
|
||||||
/** Return {@link PointValues} for the given {@code field}. */
|
/**
|
||||||
|
* Return {@link PointValues} for the given {@code field}. The behavior is undefined if the given
|
||||||
|
* field doesn't have points enabled on its {@link FieldInfo}.
|
||||||
|
*/
|
||||||
public abstract PointValues getValues(String field) throws IOException;
|
public abstract PointValues getValues(String field) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -226,19 +226,13 @@ public final class Lucene90HnswVectorsReader extends KnnVectorsReader {
|
||||||
@Override
|
@Override
|
||||||
public VectorValues getVectorValues(String field) throws IOException {
|
public VectorValues getVectorValues(String field) throws IOException {
|
||||||
FieldEntry fieldEntry = fields.get(field);
|
FieldEntry fieldEntry = fields.get(field);
|
||||||
if (fieldEntry == null || fieldEntry.dimension == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return getOffHeapVectorValues(fieldEntry);
|
return getOffHeapVectorValues(fieldEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TopDocs search(String field, float[] target, int k, Bits acceptDocs) throws IOException {
|
public TopDocs search(String field, float[] target, int k, Bits acceptDocs) throws IOException {
|
||||||
FieldEntry fieldEntry = fields.get(field);
|
FieldEntry fieldEntry = fields.get(field);
|
||||||
if (fieldEntry == null || fieldEntry.dimension == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (fieldEntry.size() == 0) {
|
if (fieldEntry.size() == 0) {
|
||||||
return new TopDocs(new TotalHits(0, TotalHits.Relation.EQUAL_TO), new ScoreDoc[0]);
|
return new TopDocs(new TotalHits(0, TotalHits.Relation.EQUAL_TO), new ScoreDoc[0]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,15 +105,13 @@ public abstract class CodecReader extends LeafReader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Terms terms(String field) throws IOException {
|
public final Terms terms(String field) throws IOException {
|
||||||
// ensureOpen(); no; getPostingsReader calls this
|
ensureOpen();
|
||||||
FieldsProducer fieldsProducer = getPostingsReader();
|
FieldInfo fi = getFieldInfos().fieldInfo(field);
|
||||||
if (fieldsProducer == null) {
|
if (fi == null || fi.getIndexOptions() == IndexOptions.NONE) {
|
||||||
|
// Field does not exist or does not index postings
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// We could check the FieldInfo IndexOptions but there's no point since
|
return getPostingsReader().terms(field);
|
||||||
// PostingsReader will simply return null for fields that don't exist or that have no terms
|
|
||||||
// index.
|
|
||||||
return fieldsProducer.terms(field);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the FieldInfo that corresponds to the given field and type, or
|
// returns the FieldInfo that corresponds to the given field and type, or
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.apache.lucene.codecs.KnnVectorsFormat;
|
||||||
import org.apache.lucene.codecs.KnnVectorsReader;
|
import org.apache.lucene.codecs.KnnVectorsReader;
|
||||||
import org.apache.lucene.codecs.KnnVectorsWriter;
|
import org.apache.lucene.codecs.KnnVectorsWriter;
|
||||||
import org.apache.lucene.index.FieldInfo;
|
import org.apache.lucene.index.FieldInfo;
|
||||||
|
import org.apache.lucene.index.FieldInfos;
|
||||||
import org.apache.lucene.index.SegmentReadState;
|
import org.apache.lucene.index.SegmentReadState;
|
||||||
import org.apache.lucene.index.SegmentWriteState;
|
import org.apache.lucene.index.SegmentWriteState;
|
||||||
import org.apache.lucene.index.VectorValues;
|
import org.apache.lucene.index.VectorValues;
|
||||||
|
@ -45,7 +46,7 @@ public class AssertingKnnVectorsFormat extends KnnVectorsFormat {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KnnVectorsReader fieldsReader(SegmentReadState state) throws IOException {
|
public KnnVectorsReader fieldsReader(SegmentReadState state) throws IOException {
|
||||||
return new AssertingKnnVectorsReader(delegate.fieldsReader(state));
|
return new AssertingKnnVectorsReader(delegate.fieldsReader(state), state.fieldInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AssertingKnnVectorsWriter extends KnnVectorsWriter {
|
static class AssertingKnnVectorsWriter extends KnnVectorsWriter {
|
||||||
|
@ -76,10 +77,12 @@ public class AssertingKnnVectorsFormat extends KnnVectorsFormat {
|
||||||
|
|
||||||
static class AssertingKnnVectorsReader extends KnnVectorsReader {
|
static class AssertingKnnVectorsReader extends KnnVectorsReader {
|
||||||
final KnnVectorsReader delegate;
|
final KnnVectorsReader delegate;
|
||||||
|
final FieldInfos fis;
|
||||||
|
|
||||||
AssertingKnnVectorsReader(KnnVectorsReader delegate) {
|
AssertingKnnVectorsReader(KnnVectorsReader delegate, FieldInfos fis) {
|
||||||
assert delegate != null;
|
assert delegate != null;
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
|
this.fis = fis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -89,17 +92,20 @@ public class AssertingKnnVectorsFormat extends KnnVectorsFormat {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VectorValues getVectorValues(String field) throws IOException {
|
public VectorValues getVectorValues(String field) throws IOException {
|
||||||
|
FieldInfo fi = fis.fieldInfo(field);
|
||||||
|
assert fi != null && fi.getVectorDimension() > 0;
|
||||||
VectorValues values = delegate.getVectorValues(field);
|
VectorValues values = delegate.getVectorValues(field);
|
||||||
if (values != null) {
|
assert values != null;
|
||||||
assert values.docID() == -1;
|
assert values.docID() == -1;
|
||||||
assert values.size() >= 0;
|
assert values.size() >= 0;
|
||||||
assert values.dimension() > 0;
|
assert values.dimension() > 0;
|
||||||
}
|
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TopDocs search(String field, float[] target, int k, Bits acceptDocs) throws IOException {
|
public TopDocs search(String field, float[] target, int k, Bits acceptDocs) throws IOException {
|
||||||
|
FieldInfo fi = fis.fieldInfo(field);
|
||||||
|
assert fi != null && fi.getVectorDimension() > 0;
|
||||||
TopDocs hits = delegate.search(field, target, k, acceptDocs);
|
TopDocs hits = delegate.search(field, target, k, acceptDocs);
|
||||||
assert hits != null;
|
assert hits != null;
|
||||||
assert hits.scoreDocs.length <= k;
|
assert hits.scoreDocs.length <= k;
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.apache.lucene.codecs.PointsFormat;
|
||||||
import org.apache.lucene.codecs.PointsReader;
|
import org.apache.lucene.codecs.PointsReader;
|
||||||
import org.apache.lucene.codecs.PointsWriter;
|
import org.apache.lucene.codecs.PointsWriter;
|
||||||
import org.apache.lucene.index.FieldInfo;
|
import org.apache.lucene.index.FieldInfo;
|
||||||
|
import org.apache.lucene.index.FieldInfos;
|
||||||
import org.apache.lucene.index.MergeState;
|
import org.apache.lucene.index.MergeState;
|
||||||
import org.apache.lucene.index.PointValues;
|
import org.apache.lucene.index.PointValues;
|
||||||
import org.apache.lucene.index.SegmentReadState;
|
import org.apache.lucene.index.SegmentReadState;
|
||||||
|
@ -54,18 +55,21 @@ public final class AssertingPointsFormat extends PointsFormat {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PointsReader fieldsReader(SegmentReadState state) throws IOException {
|
public PointsReader fieldsReader(SegmentReadState state) throws IOException {
|
||||||
return new AssertingPointsReader(state.segmentInfo.maxDoc(), in.fieldsReader(state), false);
|
return new AssertingPointsReader(
|
||||||
|
state.segmentInfo.maxDoc(), in.fieldsReader(state), state.fieldInfos, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AssertingPointsReader extends PointsReader {
|
static class AssertingPointsReader extends PointsReader {
|
||||||
private final PointsReader in;
|
private final PointsReader in;
|
||||||
private final int maxDoc;
|
private final int maxDoc;
|
||||||
|
private final FieldInfos fis;
|
||||||
private final boolean merging;
|
private final boolean merging;
|
||||||
private final Thread creationThread;
|
private final Thread creationThread;
|
||||||
|
|
||||||
AssertingPointsReader(int maxDoc, PointsReader in, boolean merging) {
|
AssertingPointsReader(int maxDoc, PointsReader in, FieldInfos fis, boolean merging) {
|
||||||
this.in = in;
|
this.in = in;
|
||||||
this.maxDoc = maxDoc;
|
this.maxDoc = maxDoc;
|
||||||
|
this.fis = fis;
|
||||||
this.merging = merging;
|
this.merging = merging;
|
||||||
this.creationThread = Thread.currentThread();
|
this.creationThread = Thread.currentThread();
|
||||||
// do a few simple checks on init
|
// do a few simple checks on init
|
||||||
|
@ -80,6 +84,8 @@ public final class AssertingPointsFormat extends PointsFormat {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PointValues getValues(String field) throws IOException {
|
public PointValues getValues(String field) throws IOException {
|
||||||
|
FieldInfo fi = fis.fieldInfo(field);
|
||||||
|
assert fi != null && fi.getPointDimensionCount() > 0;
|
||||||
if (merging) {
|
if (merging) {
|
||||||
AssertingCodec.assertThread("PointsReader", creationThread);
|
AssertingCodec.assertThread("PointsReader", creationThread);
|
||||||
}
|
}
|
||||||
|
@ -97,7 +103,7 @@ public final class AssertingPointsFormat extends PointsFormat {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PointsReader getMergeInstance() {
|
public PointsReader getMergeInstance() {
|
||||||
return new AssertingPointsReader(maxDoc, in.getMergeInstance(), true);
|
return new AssertingPointsReader(maxDoc, in.getMergeInstance(), fis, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue