package testcases import ( "fmt" "testing" "time" "github.com/stretchr/testify/require" "go.uber.org/zap" "github.com/milvus-io/milvus/client/v2/column" "github.com/milvus-io/milvus/client/v2/entity" "github.com/milvus-io/milvus/client/v2/index" clientv2 "github.com/milvus-io/milvus/client/v2/milvusclient" "github.com/milvus-io/milvus/pkg/v2/log" "github.com/milvus-io/milvus/tests/go_client/common" hp "github.com/milvus-io/milvus/tests/go_client/testcases/helper" ) // test load collection func TestLoadCollection(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // create -> insert -> flush -> index -> load prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64Vec), hp.TNewFieldsOption(), hp.TNewSchemaOption()) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption()) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) // load loadTask, err := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName)) common.CheckErr(t, err, true) err = loadTask.Await(ctx) common.CheckErr(t, err, true) // describe collection coll, err := mc.DescribeCollection(ctx, clientv2.NewDescribeCollectionOption(schema.CollectionName)) common.CheckErr(t, err, true) t.Log("https://github.com/milvus-io/milvus/issues/34149") log.Debug("collection", zap.Bool("loaded", coll.Loaded)) res, err := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithConsistencyLevel(entity.ClStrong).WithOutputFields(common.QueryCountFieldName)) common.CheckErr(t, err, true) count, _ := res.GetColumn(common.QueryCountFieldName).GetAsInt64(0) require.EqualValues(t, common.DefaultNb, count) } // test load not existed collection func TestLoadCollectionNotExist(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) // connect mc := hp.CreateDefaultMilvusClient(ctx, t) // Load collection _, errLoad := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption("collName")) common.CheckErr(t, errLoad, false, "collection not found[database=default][collection=collName]") } // test load collection async func TestLoadCollectionAsync(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // create -> insert -> flush -> index -> load prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64Vec), hp.TNewFieldsOption(), hp.TNewSchemaOption()) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption()) prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) // load _, err := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName)) common.CheckErr(t, err, true) // query res, err := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.QueryCountFieldName)) common.CheckErr(t, err, true) count, _ := res.GetColumn(common.QueryCountFieldName).GetAsInt64(0) require.LessOrEqual(t, count, int64(common.DefaultNb*2)) } // load collection without index func TestLoadCollectionWithoutIndex(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // create -> insert -> flush -> index -> load prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64Vec), hp.TNewFieldsOption(), hp.TNewSchemaOption()) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption()) // load _, errLoad := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName)) common.CheckErr(t, errLoad, false, "index not found") // load partitions without index _, errLoadPartition := mc.LoadPartitions(ctx, clientv2.NewLoadPartitionsOption(schema.CollectionName, common.DefaultPartition)) common.CheckErr(t, errLoadPartition, false, "index not found") } // load collection with multi partitions func TestLoadCollectionMultiPartitions(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) parName := common.GenRandomString("p", 4) // create collection and partition prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64Vec), hp.TNewFieldsOption(), hp.TNewSchemaOption()) err := mc.CreatePartition(ctx, clientv2.NewCreatePartitionOption(schema.CollectionName, parName)) common.CheckErr(t, err, true) // insert [0, nb) into default partition, [nb, nb*2) into new partition prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption().TWithNb(common.DefaultNb)) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema).TWithPartitionName(parName), hp.TNewDataOption().TWithNb(common.DefaultNb).TWithStart(common.DefaultNb)) // create index prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) // load default partition taskDef, errDef := mc.LoadPartitions(ctx, clientv2.NewLoadPartitionsOption(schema.CollectionName, common.DefaultPartition)) common.CheckErr(t, errDef, true) err = taskDef.Await(ctx) common.CheckErr(t, err, true) // query from parName -> error _, err = mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.QueryCountFieldName).WithPartitions(parName)) log.Debug("error", zap.Error(err)) common.CheckErr(t, err, false, "partition not loaded") // query count(*) from default partition res, err := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.QueryCountFieldName).WithPartitions(common.DefaultPartition).WithConsistencyLevel(entity.ClStrong)) common.CheckErr(t, err, true) count, _ := res.GetColumn(common.QueryCountFieldName).GetAsInt64(0) require.Equal(t, int64(common.DefaultNb), count) // load parName partitions taskPar, errPar := mc.LoadPartitions(ctx, clientv2.NewLoadPartitionsOption(schema.CollectionName, parName)) common.CheckErr(t, errPar, true) err = taskPar.Await(ctx) common.CheckErr(t, err, true) // query count(*) from all partitions res, err = mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.QueryCountFieldName).WithPartitions(parName, common.DefaultPartition).WithConsistencyLevel(entity.ClStrong)) common.CheckErr(t, err, true) count, _ = res.GetColumn(common.QueryCountFieldName).GetAsInt64(0) require.Equal(t, int64(common.DefaultNb*2), count) // release collection -> load all partitions -> query count(*) all partitions 6000 mc.ReleaseCollection(ctx, clientv2.NewReleaseCollectionOption(schema.CollectionName)) mc.LoadPartitions(ctx, clientv2.NewLoadPartitionsOption(schema.CollectionName, parName, common.DefaultPartition)) res, err = mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.QueryCountFieldName).WithConsistencyLevel(entity.ClStrong)) common.CheckErr(t, err, true) count, _ = res.GetColumn(common.QueryCountFieldName).GetAsInt64(0) require.Equal(t, int64(common.DefaultNb*2), count) } // test load repeated partition names func TestLoadPartitionsRepeatedly(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) parName := common.GenRandomString("p", 4) // create collection and partition prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64Vec), hp.TNewFieldsOption(), hp.TNewSchemaOption()) err := mc.CreatePartition(ctx, clientv2.NewCreatePartitionOption(schema.CollectionName, parName)) common.CheckErr(t, err, true) _parPk := hp.GenColumnData(common.DefaultNb, entity.FieldTypeInt64, *hp.TNewDataOption().TWithStart(common.DefaultNb)) _parVec := hp.GenColumnData(common.DefaultNb, entity.FieldTypeFloatVector, *hp.TNewDataOption().TWithStart(common.DefaultNb)) insertRes2, err2 := mc.Insert(ctx, clientv2.NewColumnBasedInsertOption(schema.CollectionName).WithColumns(_parPk, _parVec).WithPartition(parName)) common.CheckErr(t, err2, true) require.EqualValues(t, common.DefaultNb, insertRes2.InsertCount) // create index prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) // load partition with repeated names taskDef, errDef := mc.LoadPartitions(ctx, clientv2.NewLoadPartitionsOption(schema.CollectionName, parName)) common.CheckErr(t, errDef, true) err = taskDef.Await(ctx) common.CheckErr(t, err, true) // query count(*) from default partition res, err := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.QueryCountFieldName).WithConsistencyLevel(entity.ClStrong)) common.CheckErr(t, err, true) count, _ := res.GetColumn(common.QueryCountFieldName).GetAsInt64(0) require.EqualValues(t, common.DefaultNb, count) } func TestLoadMultiVectorsIndex(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // create collection -> insert -> flush -> index _, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64MultiVec), hp.TNewFieldsOption(), hp.TNewSchemaOption().TWithEnableDynamicField(true)) hnswIdx := index.NewHNSWIndex(entity.IP, 8, 200) for _, fieldName := range []string{common.DefaultFloatVecFieldName, common.DefaultFloat16VecFieldName, common.DefaultBFloat16VecFieldName} { idxTask, err := mc.CreateIndex(ctx, clientv2.NewCreateIndexOption(schema.CollectionName, fieldName, hnswIdx)) common.CheckErr(t, err, true) err = idxTask.Await(ctx) common.CheckErr(t, err, true) } _, err := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName)) common.CheckErr(t, err, false, "there is no vector index on field") } func TestLoadCollectionAllFields(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // create collection -> insert -> flush -> index prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.AllFields), hp.TNewFieldsOption(), hp.TNewSchemaOption().TWithEnableDynamicField(true)) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption()) prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) // load collection loadTask, err := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName)) common.CheckErr(t, err, true) err = loadTask.Await(ctx) common.CheckErr(t, err, true) // query count(*) res, err := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.QueryCountFieldName).WithConsistencyLevel(entity.ClStrong)) common.CheckErr(t, err, true) count, _ := res.GetColumn(common.QueryCountFieldName).GetAsInt64(0) require.EqualValues(t, common.DefaultNb, count) } func TestLoadCollectionSparse(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // create collection -> insert -> flush -> index prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64VarcharSparseVec), hp.TNewFieldsOption(), hp.TNewSchemaOption().TWithEnableDynamicField(true)) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption().TWithSparseMaxLen(200)) prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) // load collection loadTask, err := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName)) common.CheckErr(t, err, true) err = loadTask.Await(ctx) common.CheckErr(t, err, true) // query count(*) res, err := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.QueryCountFieldName).WithConsistencyLevel(entity.ClStrong)) common.CheckErr(t, err, true) count, _ := res.GetColumn(common.QueryCountFieldName).GetAsInt64(0) require.EqualValues(t, common.DefaultNb, count) } func TestLoadPartialFields(t *testing.T) { /* 1. verify the collection loaded successfully 2. verify the loaded fields can be searched in expr and output_fields 3. verify the skip fields not loaded, and cannot search/query/hybrid search with them in expr or output_fields */ // create collection -> insert -> flush -> index ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.AllFields), hp.TNewFieldsOption(), hp.TNewSchemaOption()) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption()) prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) // load partial fields partialLoadedFields := []string{common.DefaultInt64FieldName, common.DefaultVarcharFieldName, common.DefaultFloatVecFieldName, common.DefaultFloat16VecFieldName} loadTask, err := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithLoadFields(partialLoadedFields...).WithSkipLoadDynamicField(true)) common.CheckErr(t, err, true) err = loadTask.Await(ctx) common.CheckErr(t, err, true) expr := fmt.Sprintf("%s > '2' ", common.DefaultVarcharFieldName) vectors := hp.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector) hintLoadedVectors := hp.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeBFloat16Vector) // search loaded fields & loaded fields expr & output loaded fields searchRes, err := mc.Search(ctx, clientv2.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).WithANNSField(common.DefaultFloatVecFieldName).WithOutputFields(partialLoadedFields...).WithFilter(expr)) common.CheckErr(t, err, true) common.CheckSearchResult(t, searchRes, common.DefaultNq, common.DefaultLimit) common.CheckOutputFields(t, partialLoadedFields, searchRes[0].Fields) // search with loaded group by field groupByRes, err := mc.Search(ctx, clientv2.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).WithANNSField(common.DefaultFloatVecFieldName).WithGroupByField(common.DefaultInt64FieldName)) common.CheckErr(t, err, true) common.CheckSearchResult(t, groupByRes, common.DefaultNq, common.DefaultLimit) // group by with not-loaded fields _, err = mc.Search(ctx, clientv2.NewSearchOption(schema.CollectionName, common.DefaultLimit, hintLoadedVectors).WithGroupByField(common.DefaultBoolFieldName)) common.CheckErr(t, err, false, "multiple anns_fields exist, please specify a anns_field in search_params") groupByRes, err = mc.Search(ctx, clientv2.NewSearchOption(schema.CollectionName, common.DefaultLimit, hintLoadedVectors).WithANNSField(common.DefaultBFloat16VecFieldName).WithGroupByField(common.DefaultInt32FieldName)) common.CheckErr(t, err, true) common.CheckSearchResult(t, groupByRes, common.DefaultNq, common.DefaultLimit) // search with not-loaded anns field -> ok hintLoadedVectors2 := hp.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloat16Vector) searchRes, err = mc.Search(ctx, clientv2.NewSearchOption(schema.CollectionName, common.DefaultLimit, hintLoadedVectors2).WithANNSField(common.DefaultFloat16VecFieldName)) common.CheckErr(t, err, true) common.CheckSearchResult(t, searchRes, common.DefaultNq, common.DefaultLimit) // search with expr not loaded field -> ok invalidExpr := fmt.Sprintf("%s > 2.0 ", common.DefaultFloatFieldName) _, err = mc.Search(ctx, clientv2.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).WithANNSField(common.DefaultFloatVecFieldName).WithFilter(invalidExpr)) common.CheckErr(t, err, true) // search with output_fields not loaded field -> ok searchRes, err = mc.Search(ctx, clientv2.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).WithANNSField(common.DefaultFloatVecFieldName).WithOutputFields("*")) common.CheckErr(t, err, true) // actually, the output fields is all fields allFieldsName := make([]string, 0, len(schema.Fields)) for _, field := range schema.Fields { allFieldsName = append(allFieldsName, field.Name) } common.CheckOutputFields(t, allFieldsName, searchRes[0].Fields) } func TestLoadPartialFieldsExpr(t *testing.T) { /* 1. verify the collection loaded successfully 2. verify the loaded / not-loaded fields can be searched in expr 3. verify the loaded / not-loaded fields can be searched in template expr */ // create collection -> insert -> flush -> index ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.AllFields), hp.TNewFieldsOption(), hp.TNewSchemaOption()) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption()) prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) // load partial fields partialLoadedFields := []string{common.DefaultInt64FieldName, common.DefaultFloatFieldName, common.DefaultFloatVecFieldName, common.DefaultFloat16VecFieldName} loadTask, err := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithLoadFields(partialLoadedFields...).WithSkipLoadDynamicField(true)) common.CheckErr(t, err, true) err = loadTask.Await(ctx) common.CheckErr(t, err, true) expr := fmt.Sprintf("%s > 500.0 ", common.DefaultDoubleFieldName) vectors := hp.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector) // search with loaded field expr searchRes, err := mc.Search(ctx, clientv2.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).WithANNSField(common.DefaultFloatVecFieldName). WithOutputFields(common.DefaultDoubleFieldName).WithFilter(expr)) common.CheckErr(t, err, true) common.CheckSearchResult(t, searchRes, common.DefaultNq, common.DefaultLimit) // verify search result meets expr condition for _, res := range searchRes { for _, value := range res.GetColumn(common.DefaultDoubleFieldName).(*column.ColumnDouble).Data() { require.Greater(t, value, 500.0) } } // search with not-loaded template expr searchRes, err = mc.Search(ctx, clientv2.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).WithANNSField(common.DefaultFloatVecFieldName). WithOutputFields(common.DefaultBoolFieldName).WithFilter("bool == {boolValue}").WithTemplateParam("boolValue", true)) common.CheckErr(t, err, true) common.CheckSearchResult(t, searchRes, common.DefaultNq, common.DefaultLimit) // verify search result meets expr condition for _, res := range searchRes { for _, value := range res.GetColumn(common.DefaultBoolFieldName).(*column.ColumnBool).Data() { require.Equal(t, value, true) } } } func TestLoadSkipDynamicField(t *testing.T) { /* 1. load -> search output dynamic field 2. reload and skip dynamic field verify: - search output dynamic field -> error - search with dynamic field in expr -> error */ // create collection -> insert -> flush -> index ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // create collection -> insert -> flush -> index -> load prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64Vec), hp.TNewFieldsOption(), hp.TNewSchemaOption().TWithEnableDynamicField(true)) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption()) prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) prepare.Load(ctx, t, mc, hp.NewLoadParams(schema.CollectionName)) // query and verify output dynamic fields queryRes, err := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.DefaultDynamicFieldName).WithLimit(10)) common.CheckErr(t, err, true) common.CheckOutputFields(t, []string{common.DefaultDynamicFieldName, common.DefaultInt64FieldName}, queryRes.Fields) // reload and skip dynamic field mc.ReleaseCollection(ctx, clientv2.NewReleaseCollectionOption(schema.CollectionName)) loadTask, err := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithSkipLoadDynamicField(true)) common.CheckErr(t, err, true) err = loadTask.Await(ctx) common.CheckErr(t, err, true) // search and verify output dynamic fields res, err := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.DefaultDynamicNumberField).WithLimit(10)) common.CheckErr(t, err, true) common.CheckOutputFields(t, []string{common.DefaultDynamicNumberField, common.DefaultInt64FieldName}, res.Fields) _, err = mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithFilter(fmt.Sprintf("%s > 0", common.DefaultDynamicNumberField))) common.CheckErr(t, err, true) } func TestLoadPartialHybridSearch(t *testing.T) { /* 1. load partial vector fields 2. hybrid search with loaded and not-loaded fields */ // create collection -> insert -> flush -> index ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // create collection -> insert -> flush -> index prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64MultiVec), hp.TNewFieldsOption(), hp.TNewSchemaOption()) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption()) prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) // load partial vector fields prepare.Load(ctx, t, mc, hp.NewLoadParams(schema.CollectionName).TWithLoadFields(common.DefaultInt64FieldName, common.DefaultFloatVecFieldName, common.DefaultBinaryVecFieldName)) // hybrid search with loaded fields floatVectors := hp.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector) binaryVectors := hp.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeBinaryVector) hybridSearchRes, err := mc.HybridSearch(ctx, clientv2.NewHybridSearchOption(schema.CollectionName, common.DefaultLimit, clientv2.NewAnnRequest(common.DefaultFloatVecFieldName, common.DefaultLimit, floatVectors...), clientv2.NewAnnRequest(common.DefaultBinaryVecFieldName, common.DefaultLimit+5, binaryVectors...))) common.CheckErr(t, err, true) common.CheckSearchResult(t, hybridSearchRes, common.DefaultNq, common.DefaultLimit) // hybrid search with not-loaded fields fp16Vectors := hp.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloat16Vector) bf16Vectors := hp.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeBFloat16Vector) hybridSearchRes, err = mc.HybridSearch(ctx, clientv2.NewHybridSearchOption(schema.CollectionName, common.DefaultLimit, clientv2.NewAnnRequest(common.DefaultFloat16VecFieldName, common.DefaultLimit-1, fp16Vectors...), clientv2.NewAnnRequest(common.DefaultBFloat16VecFieldName, common.DefaultLimit+5, bf16Vectors...))) common.CheckErr(t, err, true) common.CheckSearchResult(t, hybridSearchRes, common.DefaultNq, common.DefaultLimit) } func TestLoadPartialFieldsPartitions(t *testing.T) { /* 1. insert data into default partition and parName partition 2. load default partition with partial fields -> succ & query 3. load parName partition with different partial fields -> hint load different fields 4. load parName partition with same partial fields -> succ 5. query from default partition and parName partition -> count=2*nb */ // no [pk, clustering, part dynamic fields] field, not all fields ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) parName := common.GenRandomString("p", 4) // create collection and partition prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64VecAllScalar), hp.TNewFieldsOption(), hp.TNewSchemaOption()) err := mc.CreatePartition(ctx, clientv2.NewCreatePartitionOption(schema.CollectionName, parName)) common.CheckErr(t, err, true) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption().TWithNb(common.DefaultNb)) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema).TWithPartitionName(parName), hp.TNewDataOption().TWithNb(common.DefaultNb).TWithStart(common.DefaultNb)) // create index prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) // load default partition with partial fields partitionFields := []string{common.DefaultInt64FieldName, common.DefaultFloatVecFieldName, common.DefaultBoolFieldName} taskDef, errDef := mc.LoadPartitions(ctx, clientv2.NewLoadPartitionsOption(schema.CollectionName, common.DefaultPartition).WithLoadFields(partitionFields...)) common.CheckErr(t, errDef, true) err = taskDef.Await(ctx) common.CheckErr(t, err, true) // query from default partition queryDefault, errQuery := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(partitionFields...).WithPartitions(common.DefaultPartition).WithLimit(common.DefaultLimit)) common.CheckErr(t, errQuery, true) common.CheckOutputFields(t, partitionFields, queryDefault.Fields) // load parName partition with different partial fields diffFields := []string{common.DefaultInt64FieldName, common.DefaultFloatVecFieldName, common.DefaultVarcharFieldName} _, errPar := mc.LoadPartitions(ctx, clientv2.NewLoadPartitionsOption(schema.CollectionName, parName).WithLoadFields(diffFields...)) common.CheckErr(t, errPar, true) queryPar, errPar := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(diffFields...).WithPartitions(parName).WithLimit(common.DefaultLimit)) common.CheckErr(t, errPar, true) common.CheckOutputFields(t, diffFields, queryPar.Fields) // load parName partition with different partial fields taskPar, errPar := mc.LoadPartitions(ctx, clientv2.NewLoadPartitionsOption(schema.CollectionName, parName).WithLoadFields(partitionFields...)) common.CheckErr(t, errPar, true) err = taskPar.Await(ctx) common.CheckErr(t, err, true) // query from default partition and parName partition countMultiPartitions, err := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.QueryCountFieldName)) common.CheckErr(t, err, true) count, _ := countMultiPartitions.GetColumn(common.QueryCountFieldName).GetAsInt64(0) require.Equal(t, int64(common.DefaultNb*2), count) } func TestLoadPartialFieldsWithoutPartitionKey(t *testing.T) { /* code fields: pk, clustering key, partition key, part dynamic fields, non-vector fields -> error not index: error */ ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // define fields & schema pkField := entity.NewField().WithName("pk").WithDataType(entity.FieldTypeInt64).WithIsPrimaryKey(true) partitionKeyField := entity.NewField().WithName("partition_key").WithDataType(entity.FieldTypeInt64).WithIsPartitionKey(true) clusteringKeyField := entity.NewField().WithName("clustering_key").WithDataType(entity.FieldTypeInt64).WithIsClusteringKey(true) vecField := entity.NewField().WithName("vec").WithDataType(entity.FieldTypeFloatVector).WithDim(common.DefaultDim) schema := entity.NewSchema().WithName(common.GenRandomString("partial", 4)).WithField(pkField).WithField(partitionKeyField).WithField(clusteringKeyField).WithField(vecField).WithDynamicFieldEnabled(true) mc.CreateCollection(ctx, clientv2.NewCreateCollectionOption(schema.CollectionName, schema)) // load partial fields without partition key fields _, err := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithLoadFields(pkField.Name, vecField.Name)) common.CheckErr(t, err, false, "does not contain partition key field partition_key") // load partial fields without clustering key fields _, err = mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithLoadFields(partitionKeyField.Name, pkField.Name, vecField.Name)) common.CheckErr(t, err, false, "does not contain clustering key field clustering_key") // load partial fields without pk _, err = mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithLoadFields(partitionKeyField.Name, clusteringKeyField.Name, vecField.Name)) common.CheckErr(t, err, false, "does not contain primary key field pk") // load partial fields without vector fields _, err = mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithLoadFields(partitionKeyField.Name, clusteringKeyField.Name, pkField.Name)) common.CheckErr(t, err, false, "does not contain vector field") _, err = mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithLoadFields(partitionKeyField.Name, clusteringKeyField.Name, pkField.Name, vecField.Name)) common.CheckErr(t, err, false, "index not found") // create index hp.CollPrepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) _, err = mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithLoadFields(partitionKeyField.Name, clusteringKeyField.Name, pkField.Name, vecField.Name)) common.CheckErr(t, err, true) } func TestLoadPartialFieldsRepeated(t *testing.T) { /* 1. repeated Load with different LoadFields -> hint loaded */ ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // create collection -> insert -> flush -> index -> load prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64VecArray), hp.TNewFieldsOption(), hp.TNewSchemaOption().TWithEnableDynamicField(true)) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption()) prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) loadTask, err := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithLoadFields(common.DefaultInt64FieldName, common.DefaultFloatVecFieldName, common.DefaultInt64ArrayField)) common.CheckErr(t, err, true) err = loadTask.Await(ctx) common.CheckErr(t, err, true) // load with different fields _, err = mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithLoadFields(common.DefaultInt64FieldName, common.DefaultFloatVecFieldName, common.DefaultVarcharArrayField)) common.CheckErr(t, err, true) // query output * resQuery, err := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields("*").WithLimit(common.DefaultLimit)) common.CheckErr(t, err, true) expFieldsName := []string{common.DefaultDynamicFieldName} for _, field := range schema.Fields { expFieldsName = append(expFieldsName, field.Name) } common.CheckOutputFields(t, expFieldsName, resQuery.Fields) } func TestLoadPartialFieldsRelease(t *testing.T) { /* 1. release collection after loading partial fields -> ok */ ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // create collection -> insert -> flush -> index -> load prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64VecArray), hp.TNewFieldsOption(), hp.TNewSchemaOption().TWithEnableDynamicField(true)) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption()) prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) loadTask, err := mc.LoadCollection(ctx, clientv2.NewLoadCollectionOption(schema.CollectionName).WithLoadFields(common.DefaultInt64FieldName, common.DefaultFloatVecFieldName, common.DefaultInt64ArrayField)) common.CheckErr(t, err, true) err = loadTask.Await(ctx) common.CheckErr(t, err, true) // release collection err = mc.ReleaseCollection(ctx, clientv2.NewReleaseCollectionOption(schema.CollectionName)) common.CheckErr(t, err, true) // verify release _, err = mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithLimit(common.DefaultLimit)) common.CheckErr(t, err, false, "collection not loaded") } func TestReleaseCollection(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) // create -> insert -> flush -> index -> load prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64Vec), hp.TNewFieldsOption(), hp.TNewSchemaOption()) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption().TWithNb(100)) prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) prepare.Load(ctx, t, mc, hp.NewLoadParams(schema.CollectionName)) // release collection err := mc.ReleaseCollection(ctx, clientv2.NewReleaseCollectionOption(schema.CollectionName)) common.CheckErr(t, err, true) // query count(*) -> error _, err = mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.QueryCountFieldName).WithConsistencyLevel(entity.ClStrong)) common.CheckErr(t, err, false, "collection not loaded") } func TestReleaseCollectionNotExist(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) // connect mc := hp.CreateDefaultMilvusClient(ctx, t) // Load collection errLoad := mc.ReleaseCollection(ctx, clientv2.NewReleaseCollectionOption("collName")) common.CheckErr(t, errLoad, false, "collection not found[database=default][collection=collName]") } func TestReleasePartitions(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) mc := hp.CreateDefaultMilvusClient(ctx, t) parName := common.GenRandomString("p", 4) nb := 100 // create collection and partition prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64Vec), hp.TNewFieldsOption(), hp.TNewSchemaOption()) err := mc.CreatePartition(ctx, clientv2.NewCreatePartitionOption(schema.CollectionName, parName)) common.CheckErr(t, err, true) // insert [0, nb) into default partition and new partition prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption().TWithNb(nb)) prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema).TWithPartitionName(parName), hp.TNewDataOption().TWithNb(nb).TWithStart(nb)) // create index prepare.FlushData(ctx, t, mc, schema.CollectionName) prepare.CreateIndex(ctx, t, mc, hp.TNewIndexParams(schema)) prepare.Load(ctx, t, mc, hp.NewLoadParams(schema.CollectionName)) // release partition errRelease := mc.ReleasePartitions(ctx, clientv2.NewReleasePartitionsOptions(schema.CollectionName, parName, common.DefaultPartition)) common.CheckErr(t, errRelease, true) // check release success _, errQuery := mc.Query(ctx, clientv2.NewQueryOption(schema.CollectionName).WithOutputFields(common.QueryCountFieldName).WithPartitions(parName)) common.CheckErr(t, errQuery, false, "collection not loaded") } func TestReleasePartitionsNotExist(t *testing.T) { ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout) // connect mc := hp.CreateDefaultMilvusClient(ctx, t) // Load collection _, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64Vec), hp.TNewFieldsOption(), hp.TNewSchemaOption()) errLoad := mc.ReleasePartitions(ctx, clientv2.NewReleasePartitionsOptions(schema.CollectionName, "parName")) common.CheckErr(t, errLoad, false, "partition not found") }