3232import org .elasticsearch .core .IOUtils ;
3333import org .elasticsearch .search .vectors .IVFKnnSearchStrategy ;
3434
35+ import java .io .Closeable ;
3536import java .io .IOException ;
37+ import java .util .ArrayList ;
38+ import java .util .Collections ;
39+ import java .util .List ;
40+ import java .util .Map ;
3641
3742import static org .apache .lucene .codecs .lucene99 .Lucene99HnswVectorsReader .SIMILARITY_FUNCTIONS ;
3843import static org .elasticsearch .index .codec .vectors .diskbbq .ES920DiskBBQVectorsFormat .DYNAMIC_VISIT_RATIO ;
@@ -46,14 +51,14 @@ public abstract class IVFVectorsReader extends KnnVectorsReader {
4651 private final SegmentReadState state ;
4752 private final FieldInfos fieldInfos ;
4853 protected final IntObjectHashMap <FieldEntry > fields ;
49- private final FlatVectorsReader rawVectorsReader ;
54+ private final Map < String , FlatVectorsReader > rawVectorReaders ;
5055
5156 @ SuppressWarnings ("this-escape" )
52- protected IVFVectorsReader (SegmentReadState state , FlatVectorsReader rawVectorsReader ) throws IOException {
57+ protected IVFVectorsReader (SegmentReadState state , Map < String , FlatVectorsReader > rawVectorReaders ) throws IOException {
5358 this .state = state ;
5459 this .fieldInfos = state .fieldInfos ;
55- this .rawVectorsReader = rawVectorsReader ;
5660 this .fields = new IntObjectHashMap <>();
61+ this .rawVectorReaders = rawVectorReaders ;
5762 String meta = IndexFileNames .segmentFileName (
5863 state .segmentInfo .name ,
5964 state .segmentSuffix ,
@@ -212,26 +217,34 @@ private static VectorEncoding readVectorEncoding(DataInput input) throws IOExcep
212217
213218 @ Override
214219 public final void checkIntegrity () throws IOException {
215- rawVectorsReader .checkIntegrity ();
220+ for (var reader : rawVectorReaders .values ()) {
221+ reader .checkIntegrity ();
222+ }
216223 CodecUtil .checksumEntireFile (ivfCentroids );
217224 CodecUtil .checksumEntireFile (ivfClusters );
218225 }
219226
227+ private FlatVectorsReader getReaderForField (String field ) {
228+ FlatVectorsReader reader = rawVectorReaders .get (field );
229+ if (reader == null ) throw new IllegalArgumentException ("No recorded raw vector reader for field " + field );
230+ return reader ;
231+ }
232+
220233 @ Override
221234 public final FloatVectorValues getFloatVectorValues (String field ) throws IOException {
222- return rawVectorsReader .getFloatVectorValues (field );
235+ return getReaderForField ( field ) .getFloatVectorValues (field );
223236 }
224237
225238 @ Override
226239 public final ByteVectorValues getByteVectorValues (String field ) throws IOException {
227- return rawVectorsReader .getByteVectorValues (field );
240+ return getReaderForField ( field ) .getByteVectorValues (field );
228241 }
229242
230243 @ Override
231244 public final void search (String field , float [] target , KnnCollector knnCollector , Bits acceptDocs ) throws IOException {
232245 final FieldInfo fieldInfo = state .fieldInfos .fieldInfo (field );
233246 if (fieldInfo .getVectorEncoding ().equals (VectorEncoding .FLOAT32 ) == false ) {
234- rawVectorsReader .search (field , target , knnCollector , acceptDocs );
247+ getReaderForField ( field ) .search (field , target , knnCollector , acceptDocs );
235248 return ;
236249 }
237250 if (fieldInfo .getVectorDimension () != target .length ) {
@@ -243,7 +256,7 @@ public final void search(String field, float[] target, KnnCollector knnCollector
243256 if (acceptDocs instanceof BitSet bitSet ) {
244257 percentFiltered = Math .max (0f , Math .min (1f , (float ) bitSet .approximateCardinality () / bitSet .length ()));
245258 }
246- int numVectors = rawVectorsReader .getFloatVectorValues (field ).size ();
259+ int numVectors = getReaderForField ( field ) .getFloatVectorValues (field ).size ();
247260 float visitRatio = DYNAMIC_VISIT_RATIO ;
248261 // Search strategy may be null if this is being called from checkIndex (e.g. from a test)
249262 if (knnCollector .getSearchStrategy () instanceof IVFKnnSearchStrategy ivfSearchStrategy ) {
@@ -309,7 +322,7 @@ public final void search(String field, float[] target, KnnCollector knnCollector
309322 @ Override
310323 public final void search (String field , byte [] target , KnnCollector knnCollector , Bits acceptDocs ) throws IOException {
311324 final FieldInfo fieldInfo = state .fieldInfos .fieldInfo (field );
312- final ByteVectorValues values = rawVectorsReader .getByteVectorValues (field );
325+ final ByteVectorValues values = getReaderForField ( field ) .getByteVectorValues (field );
313326 for (int i = 0 ; i < values .size (); i ++) {
314327 final float score = fieldInfo .getVectorSimilarityFunction ().compare (target , values .vectorValue (i ));
315328 knnCollector .collect (values .ordToDoc (i ), score );
@@ -321,7 +334,9 @@ public final void search(String field, byte[] target, KnnCollector knnCollector,
321334
322335 @ Override
323336 public void close () throws IOException {
324- IOUtils .close (rawVectorsReader , ivfCentroids , ivfClusters );
337+ List <Closeable > closeables = new ArrayList <>(rawVectorReaders .values ());
338+ Collections .addAll (closeables , ivfCentroids , ivfClusters );
339+ IOUtils .close (closeables );
325340 }
326341
327342 protected record FieldEntry (
0 commit comments