3838
3939import java .io .IOException ;
4040
41+ import static org .elasticsearch .index .mapper .vectors .DenseVectorFieldMapper .COSINE_MAGNITUDE_FIELD_SUFFIX ;
4142import static org .elasticsearch .index .mapper .vectors .DenseVectorFieldMapper .ElementType .BYTE ;
4243
4344/**
@@ -540,6 +541,11 @@ public AllReader reader(LeafReaderContext context) throws IOException {
540541 case FLOAT -> {
541542 FloatVectorValues floatVectorValues = context .reader ().getFloatVectorValues (fieldName );
542543 if (floatVectorValues != null ) {
544+ if (fieldType .isNormalized ()) {
545+ NumericDocValues magnitudeDocValues = context .reader ()
546+ .getNumericDocValues (fieldType .name () + COSINE_MAGNITUDE_FIELD_SUFFIX );
547+ return new FloatDenseVectorNormalizedValuesBlockReader (floatVectorValues , dimensions , magnitudeDocValues );
548+ }
543549 return new FloatDenseVectorValuesBlockReader (floatVectorValues , dimensions );
544550 }
545551 }
@@ -584,6 +590,9 @@ public void read(int docId, BlockLoader.StoredFields storedFields, Builder build
584590 }
585591
586592 private void read (int doc , BlockLoader .FloatBuilder builder ) throws IOException {
593+ assert vectorValues .dimension () == dimensions
594+ : "unexpected dimensions for vector value; expected " + dimensions + " but got " + vectorValues .dimension ();
595+
587596 if (iterator .docID () > doc ) {
588597 builder .appendNull ();
589598 } else if (iterator .docID () == doc || iterator .advance (doc ) == doc ) {
@@ -611,8 +620,6 @@ private static class FloatDenseVectorValuesBlockReader extends DenseVectorValues
611620
612621 protected void appendDoc (BlockLoader .FloatBuilder builder ) throws IOException {
613622 float [] floats = vectorValues .vectorValue (iterator .index ());
614- assert floats .length == dimensions
615- : "unexpected dimensions for vector value; expected " + dimensions + " but got " + floats .length ;
616623 for (float aFloat : floats ) {
617624 builder .appendFloat (aFloat );
618625 }
@@ -624,15 +631,45 @@ public String toString() {
624631 }
625632 }
626633
634+ private static class FloatDenseVectorNormalizedValuesBlockReader extends DenseVectorValuesBlockReader <FloatVectorValues > {
635+ private final NumericDocValues magnitudeDocValues ;
636+
637+ FloatDenseVectorNormalizedValuesBlockReader (
638+ FloatVectorValues floatVectorValues ,
639+ int dimensions ,
640+ NumericDocValues magnitudeDocValues
641+ ) {
642+ super (floatVectorValues , dimensions );
643+ this .magnitudeDocValues = magnitudeDocValues ;
644+ }
645+
646+ @ Override
647+ protected void appendDoc (BlockLoader .FloatBuilder builder ) throws IOException {
648+ float magnitude = 1.0f ;
649+ // If all vectors are normalized, no doc values will be present. The vector may be normalized already, so we may not have a
650+ // stored magnitude for all docs
651+ if ((magnitudeDocValues != null ) && magnitudeDocValues .advanceExact (iterator .docID ())) {
652+ magnitude = Float .intBitsToFloat ((int ) magnitudeDocValues .longValue ());
653+ }
654+ float [] floats = vectorValues .vectorValue (iterator .index ());
655+ for (float aFloat : floats ) {
656+ builder .appendFloat (aFloat * magnitude );
657+ }
658+ }
659+
660+ @ Override
661+ public String toString () {
662+ return "BlockDocValuesReader.FloatDenseVectorNormalizedValuesBlockReader" ;
663+ }
664+ }
665+
627666 private static class ByteDenseVectorValuesBlockReader extends DenseVectorValuesBlockReader <ByteVectorValues > {
628667 ByteDenseVectorValuesBlockReader (ByteVectorValues floatVectorValues , int dimensions ) {
629668 super (floatVectorValues , dimensions );
630669 }
631670
632671 protected void appendDoc (BlockLoader .FloatBuilder builder ) throws IOException {
633672 byte [] bytes = vectorValues .vectorValue (iterator .index ());
634- assert bytes .length == dimensions
635- : "unexpected dimensions for vector value; expected " + dimensions + " but got " + bytes .length ;
636673 for (byte aFloat : bytes ) {
637674 builder .appendFloat (aFloat );
638675 }
0 commit comments