feat: impl StructArray -- ban non-float-vector for now (#44875)

ref https://github.com/milvus-io/milvus/issues/42148

---------

Signed-off-by: SpadeA <tangchenjie1210@gmail.com>
This commit is contained in:
Spade A 2025-10-17 10:26:09 +08:00 committed by GitHub
parent 633cae9461
commit 6c8e353439
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 29 additions and 23 deletions

View File

@ -664,9 +664,14 @@ func ValidateFieldsInStruct(field *schemapb.FieldSchema, schema *schemapb.Collec
return fmt.Errorf("Inconsistent schema: element type of array field %s is a vector type", field.Name)
}
} else {
if !typeutil.IsVectorType(field.GetElementType()) {
return fmt.Errorf("Inconsistent schema: element type of array field %s is not a vector type", field.Name)
// TODO(SpadeA): only support float vector now
if field.GetElementType() != schemapb.DataType_FloatVector {
return fmt.Errorf("Unsupported element type of array field %s, now only float vector is supported", field.Name)
}
// if !typeutil.IsVectorType(field.GetElementType()) {
// return fmt.Errorf("Inconsistent schema: element type of array field %s is not a vector type", field.Name)
// }
err = validateDimension(field)
if err != nil {
return err

View File

@ -3957,7 +3957,7 @@ func TestValidateFieldsInStruct(t *testing.T) {
}
err := ValidateFieldsInStruct(field, schema)
assert.Error(t, err)
assert.Contains(t, err.Error(), "element type of array field array_vector_with_scalar is not a vector type")
assert.Contains(t, err.Error(), "Unsupported element type of array field array_vector_with_scalar, now only float vector is supported")
})
t.Run("array of vector missing dimension", func(t *testing.T) {
@ -4037,19 +4037,19 @@ func TestValidateFieldsInStruct(t *testing.T) {
assert.Contains(t, err.Error(), "nullable is not supported for fields in struct array now")
})
t.Run("sparse float vector in array of vector", func(t *testing.T) {
// Note: ArrayOfVector with sparse vector element type still requires dimension
// because validateDimension checks the field's DataType (ArrayOfVector), not ElementType
field := &schemapb.FieldSchema{
Name: "sparse_vector_array",
DataType: schemapb.DataType_ArrayOfVector,
ElementType: schemapb.DataType_SparseFloatVector,
TypeParams: []*commonpb.KeyValuePair{},
}
err := ValidateFieldsInStruct(field, schema)
assert.Error(t, err)
assert.Contains(t, err.Error(), "dimension is not defined")
})
// t.Run("sparse float vector in array of vector", func(t *testing.T) {
// // Note: ArrayOfVector with sparse vector element type still requires dimension
// // because validateDimension checks the field's DataType (ArrayOfVector), not ElementType
// field := &schemapb.FieldSchema{
// Name: "sparse_vector_array",
// DataType: schemapb.DataType_ArrayOfVector,
// ElementType: schemapb.DataType_SparseFloatVector,
// TypeParams: []*commonpb.KeyValuePair{},
// }
// err := ValidateFieldsInStruct(field, schema)
// assert.Error(t, err)
// assert.Contains(t, err.Error(), "dimension is not defined")
// })
t.Run("array with various scalar element types", func(t *testing.T) {
validScalarTypes := []schemapb.DataType{
@ -4077,9 +4077,9 @@ func TestValidateFieldsInStruct(t *testing.T) {
t.Run("array of vector with various vector types", func(t *testing.T) {
validVectorTypes := []schemapb.DataType{
schemapb.DataType_FloatVector,
schemapb.DataType_BinaryVector,
schemapb.DataType_Float16Vector,
schemapb.DataType_BFloat16Vector,
// schemapb.DataType_BinaryVector,
// schemapb.DataType_Float16Vector,
// schemapb.DataType_BFloat16Vector,
// Note: SparseFloatVector is excluded because validateDimension checks
// the field's DataType (ArrayOfVector), not ElementType, so it still requires dimension
}

View File

@ -997,13 +997,14 @@ func (w *NativePayloadWriter) addFloatVectorArrayToPayload(builder *array.ListBu
floatData := vectorField.GetFloatVector().GetData()
numVectors := len(floatData) / int(data.Dim)
dim := vectorField.GetDim()
numVectors := len(floatData) / int(dim)
for i := 0; i < numVectors; i++ {
start := i * int(data.Dim)
end := start + int(data.Dim)
start := i * int(dim)
end := start + int(dim)
vectorSlice := floatData[start:end]
bytes := make([]byte, data.Dim*4)
bytes := make([]byte, dim*4)
for j, f := range vectorSlice {
binary.LittleEndian.PutUint32(bytes[j*4:], math.Float32bits(f))
}