github.com/milvus-io/milvus-sdk-go/v2@v2.4.1/test/testcases/search_test.go (about)

     1  //go:build L0
     2  
     3  package testcases
     4  
     5  import (
     6  	"fmt"
     7  	"log"
     8  	"math/rand"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/milvus-io/milvus-sdk-go/v2/client"
    16  	"github.com/milvus-io/milvus-sdk-go/v2/entity"
    17  	"github.com/milvus-io/milvus-sdk-go/v2/test/common"
    18  )
    19  
    20  func TestSearch(t *testing.T) {
    21  	ctx := createContext(t, time.Second*common.DefaultTimeout)
    22  	// connect
    23  	mc := createMilvusClient(ctx, t)
    24  
    25  	// create collection with data
    26  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, true)
    27  
    28  	// load collection
    29  	errLoad := mc.LoadCollection(ctx, collName, false)
    30  	common.CheckErr(t, errLoad, true)
    31  
    32  	// search vector
    33  	sp, _ := entity.NewIndexHNSWSearchParam(74)
    34  	searchResult, errSearch := mc.Search(
    35  		ctx, collName,
    36  		[]string{common.DefaultPartition},
    37  		"",
    38  		[]string{common.DefaultFloatFieldName},
    39  		//[]entity.Vector{entity.FloatVector([]float32{0.1, 0.2})},
    40  		common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
    41  		common.DefaultFloatVecFieldName,
    42  		entity.L2,
    43  		common.DefaultTopK,
    44  		sp,
    45  	)
    46  	common.CheckErr(t, errSearch, true)
    47  	common.CheckOutputFields(t, searchResult[0].Fields, []string{common.DefaultFloatFieldName})
    48  	common.CheckSearchResult(t, searchResult, common.DefaultNq, common.DefaultTopK)
    49  }
    50  
    51  func TestSearchFloatGrowing(t *testing.T) {
    52  	t.Parallel()
    53  	for _, idx := range common.GenAllFloatIndex() {
    54  		ctx := createContext(t, time.Second*common.DefaultTimeout)
    55  		// connect
    56  		mc := createMilvusClient(ctx, t)
    57  
    58  		// create collection with all datatype
    59  		cp := CollectionParams{CollectionFieldsType: Int64FloatVec, AutoID: false, EnableDynamicField: true,
    60  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
    61  		collName := createCollection(ctx, t, mc, cp)
    62  
    63  		// create index and load
    64  		err := mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false)
    65  		common.CheckErr(t, err, true)
    66  		err = mc.LoadCollection(ctx, collName, false)
    67  		common.CheckErr(t, err, true)
    68  
    69  		// insert
    70  		dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: Int64FloatVec,
    71  			start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true, WithRows: false}
    72  		_, err = insertData(ctx, t, mc, dp)
    73  		common.CheckErr(t, err, true)
    74  
    75  		// search params
    76  		queryVec := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector)
    77  		sp, _ := entity.NewIndexBinIvfFlatSearchParam(64)
    78  		searchResult, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec,
    79  			common.DefaultFloatVecFieldName, entity.MetricType(idx.Params()["metrics_type"]), common.DefaultTopK, sp,
    80  			client.WithSearchQueryConsistencyLevel(entity.ClStrong))
    81  		common.CheckErr(t, errSearch, true)
    82  		common.CheckOutputFields(t, searchResult[0].Fields, []string{common.DefaultIntFieldName, common.DefaultFloatVecFieldName,
    83  			common.DefaultFloatFieldName, common.DefaultDynamicFieldName})
    84  		common.CheckSearchResult(t, searchResult, common.DefaultNq, common.DefaultTopK)
    85  	}
    86  }
    87  
    88  func TestSearchBinaryGrowing(t *testing.T) {
    89  	t.Parallel()
    90  	for _, metricType := range common.SupportBinIvfFlatMetricType {
    91  		idxBinIvfFlat, _ := entity.NewIndexBinIvfFlat(metricType, 128)
    92  		ctx := createContext(t, time.Second*common.DefaultTimeout)
    93  		// connect
    94  		mc := createMilvusClient(ctx, t)
    95  
    96  		// create collection with all datatype
    97  		cp := CollectionParams{CollectionFieldsType: VarcharBinaryVec, AutoID: false, EnableDynamicField: false,
    98  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
    99  		collName := createCollection(ctx, t, mc, cp)
   100  
   101  		// create index and load
   102  		err := mc.CreateIndex(ctx, collName, common.DefaultBinaryVecFieldName, idxBinIvfFlat, false)
   103  		common.CheckErr(t, err, true)
   104  		err = mc.LoadCollection(ctx, collName, false)
   105  		common.CheckErr(t, err, true)
   106  
   107  		// insert
   108  		dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: VarcharBinaryVec,
   109  			start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: false, WithRows: false}
   110  		_, err = insertData(ctx, t, mc, dp)
   111  		common.CheckErr(t, err, true)
   112  
   113  		// search params
   114  		queryVec := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeBinaryVector)
   115  		sp, _ := entity.NewIndexBinIvfFlatSearchParam(64)
   116  		searchResult, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec,
   117  			common.DefaultBinaryVecFieldName, metricType, common.DefaultTopK, sp,
   118  			client.WithSearchQueryConsistencyLevel(entity.ClStrong))
   119  		common.CheckErr(t, errSearch, true)
   120  		common.CheckOutputFields(t, searchResult[0].Fields, []string{common.DefaultVarcharFieldName, common.DefaultBinaryVecFieldName})
   121  		common.CheckSearchResult(t, searchResult, common.DefaultNq, common.DefaultTopK)
   122  	}
   123  }
   124  
   125  // test search collection not exist
   126  func TestSearchCollectionNotExist(t *testing.T) {
   127  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   128  	// connect
   129  	mc := createMilvusClient(ctx, t)
   130  
   131  	// search vector
   132  	sp, _ := entity.NewIndexHNSWSearchParam(74)
   133  	_, errSearch := mc.Search(
   134  		ctx, "collName",
   135  		[]string{common.DefaultPartition},
   136  		"",
   137  		[]string{common.DefaultFloatFieldName},
   138  		//[]entity.Vector{entity.FloatVector([]float32{0.1, 0.2})},
   139  		common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   140  		common.DefaultFloatVecFieldName,
   141  		entity.L2,
   142  		common.DefaultTopK,
   143  		sp,
   144  	)
   145  	common.CheckErr(t, errSearch, false, "can't find collection")
   146  }
   147  
   148  // test search empty collection -> return empty
   149  func TestSearchEmptyCollection(t *testing.T) {
   150  	t.Parallel()
   151  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   152  	// connect
   153  	mc := createMilvusClient(ctx, t)
   154  
   155  	for _, enableDynamicField := range []bool{true, false} {
   156  		// empty collection
   157  		collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards, client.WithEnableDynamicSchema(enableDynamicField))
   158  
   159  		idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
   160  		mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false, client.WithIndexName(""))
   161  
   162  		// load collection
   163  		errLoad := mc.LoadCollection(ctx, collName, false)
   164  		common.CheckErr(t, errLoad, true)
   165  
   166  		// search vector
   167  		sp, _ := entity.NewIndexHNSWSearchParam(74)
   168  		searchRes, errSearch := mc.Search(
   169  			ctx, collName,
   170  			[]string{common.DefaultPartition},
   171  			"",
   172  			[]string{"*"},
   173  			//[]entity.Vector{entity.FloatVector([]float32{0.1, 0.2})},
   174  			common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   175  			common.DefaultFloatVecFieldName,
   176  			entity.L2,
   177  			common.DefaultTopK,
   178  			sp,
   179  		)
   180  		common.CheckErr(t, errSearch, true)
   181  		common.CheckSearchResult(t, searchRes, common.DefaultNq, 0)
   182  	}
   183  }
   184  
   185  func TestSearchEmptyCollection2(t *testing.T) {
   186  	ctx := createContext(t, time.Second*common.DefaultTimeout*2)
   187  	// connect
   188  	mc := createMilvusClient(ctx, t)
   189  
   190  	// create -> insert [0, 3000) -> flush -> index -> load
   191  	cp := CollectionParams{CollectionFieldsType: AllFields, AutoID: false, EnableDynamicField: true,
   192  		ShardsNum: common.DefaultShards, Dim: common.DefaultDim, MaxLength: common.TestMaxLen}
   193  
   194  	dp := DataParams{DoInsert: false}
   195  
   196  	// index params
   197  	ips := GenDefaultIndexParamsForAllVectors()
   198  	collName := prepareCollection(ctx, t, mc, cp, WithDataParams(dp), WithIndexParams(ips), WithCreateOption(client.WithConsistencyLevel(entity.ClStrong)))
   199  
   200  	// search
   201  	type mNameVec struct {
   202  		fieldName  string
   203  		metricType entity.MetricType
   204  		queryVec   []entity.Vector
   205  	}
   206  	nameVecs := []mNameVec{
   207  		{fieldName: common.DefaultFloatVecFieldName, metricType: entity.L2, queryVec: common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector)},
   208  		{fieldName: common.DefaultFloat16VecFieldName, metricType: entity.L2, queryVec: common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloat16Vector)},
   209  		{fieldName: common.DefaultBFloat16VecFieldName, metricType: entity.L2, queryVec: common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeBFloat16Vector)},
   210  		{fieldName: common.DefaultBinaryVecFieldName, metricType: entity.JACCARD, queryVec: common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeBinaryVector)},
   211  	}
   212  	sp, _ := entity.NewIndexHNSWSearchParam(100)
   213  	for _, nv := range nameVecs {
   214  		resSearch, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, nv.queryVec, nv.fieldName,
   215  			nv.metricType, common.DefaultTopK, sp)
   216  		common.CheckErr(t, errSearch, true)
   217  		common.CheckSearchResult(t, resSearch, common.DefaultNq, 0)
   218  	}
   219  }
   220  
   221  // test search with partition names []string{}, []string{""}
   222  func TestSearchEmptyPartitions(t *testing.T) {
   223  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   224  	// connect
   225  	mc := createMilvusClient(ctx, t)
   226  
   227  	for _, enableDynamicField := range []bool{true, false} {
   228  		// create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition
   229  		collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards, client.WithEnableDynamicSchema(enableDynamicField))
   230  		_, vecColumnDefault, vecColumnPartition := createInsertTwoPartitions(ctx, t, mc, collName, 500)
   231  
   232  		// create index
   233  		idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
   234  		mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false)
   235  
   236  		// load with not exist partition names
   237  		errLoad := mc.LoadCollection(ctx, collName, false)
   238  		common.CheckErr(t, errLoad, true)
   239  
   240  		// search with empty partition name []string{""}
   241  		sp, _ := entity.NewIndexHNSWSearchParam(74)
   242  		_, errSearch := mc.Search(
   243  			ctx, collName,
   244  			[]string{""},
   245  			"",
   246  			[]string{common.DefaultFloatFieldName},
   247  			common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   248  			common.DefaultFloatVecFieldName,
   249  			entity.L2,
   250  			common.DefaultTopK,
   251  			sp,
   252  		)
   253  		common.CheckErr(t, errSearch, false, "Partition name should not be empty")
   254  
   255  		// search with empty partition names slice []string{}
   256  		vecDefaultData := vecColumnDefault.VectorColumn.(*entity.ColumnFloatVector).Data()[0]
   257  		vecPartitionData := vecColumnPartition.VectorColumn.(*entity.ColumnFloatVector).Data()[0]
   258  		searchResult, _ := mc.Search(
   259  			ctx, collName,
   260  			[]string{},
   261  			"",
   262  			[]string{common.DefaultFloatFieldName},
   263  			[]entity.Vector{
   264  				entity.FloatVector(vecDefaultData),
   265  				entity.FloatVector(vecPartitionData),
   266  			},
   267  			common.DefaultFloatVecFieldName,
   268  			entity.L2,
   269  			common.DefaultTopK,
   270  			sp,
   271  		)
   272  
   273  		// check search result contains search vector, which from all partitions
   274  		nq0IDs := searchResult[0].IDs.(*entity.ColumnInt64).Data()
   275  		nq1IDs := searchResult[1].IDs.(*entity.ColumnInt64).Data()
   276  		common.CheckSearchResult(t, searchResult, 2, common.DefaultTopK)
   277  		require.Contains(t, nq0IDs, vecColumnDefault.IdsColumn.(*entity.ColumnInt64).Data()[0])
   278  		require.Contains(t, nq1IDs, vecColumnPartition.IdsColumn.(*entity.ColumnInt64).Data()[0])
   279  	}
   280  }
   281  
   282  // test search with an not existed partition -> error
   283  func TestSearchPartitionNotExist(t *testing.T) {
   284  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   285  	// connect
   286  	mc := createMilvusClient(ctx, t)
   287  
   288  	// create collection with data
   289  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, false)
   290  
   291  	type notExistPartitions []string
   292  
   293  	// search partitions not exist, part exist
   294  	partitionsNotExist := []notExistPartitions{[]string{"new"}, []string{"new", common.DefaultPartition}}
   295  
   296  	for _, partitions := range partitionsNotExist {
   297  		sp, _ := entity.NewIndexHNSWSearchParam(74)
   298  		_, errSearch := mc.Search(
   299  			ctx, collName,
   300  			partitions,
   301  			"",
   302  			[]string{common.DefaultFloatFieldName},
   303  			common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   304  			common.DefaultFloatVecFieldName,
   305  			entity.L2,
   306  			common.DefaultTopK,
   307  			sp,
   308  		)
   309  		common.CheckErr(t, errSearch, false, "partition name new not found")
   310  	}
   311  }
   312  
   313  // test search single partition and multi partitions
   314  func TestSearchPartitions(t *testing.T) {
   315  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   316  	// connect
   317  	mc := createMilvusClient(ctx, t)
   318  
   319  	// create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition
   320  	collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards)
   321  	partitionName, vecColumnDefault, vecColumnPartition := createInsertTwoPartitions(ctx, t, mc, collName, 500)
   322  
   323  	// create index
   324  	idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
   325  	mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false)
   326  
   327  	// load with not exist partition names
   328  	errLoad := mc.LoadCollection(ctx, collName, false)
   329  	common.CheckErr(t, errLoad, true)
   330  
   331  	vecDefaultData := vecColumnDefault.VectorColumn.(*entity.ColumnFloatVector).Data()[0]
   332  	vecPartitionData := vecColumnPartition.VectorColumn.(*entity.ColumnFloatVector).Data()[0]
   333  
   334  	// search single partition
   335  	sp, _ := entity.NewIndexHNSWSearchParam(74)
   336  	searchSingleRes, _ := mc.Search(
   337  		ctx, collName,
   338  		[]string{common.DefaultPartition},
   339  		"",
   340  		[]string{common.DefaultFloatFieldName},
   341  		[]entity.Vector{
   342  			entity.FloatVector(vecDefaultData),
   343  			entity.FloatVector(vecPartitionData),
   344  		},
   345  		common.DefaultFloatVecFieldName,
   346  		entity.L2,
   347  		common.DefaultTopK,
   348  		sp,
   349  	)
   350  	// check search result contains search vector, which from all partitions
   351  	common.CheckSearchResult(t, searchSingleRes, 2, common.DefaultTopK)
   352  	require.Contains(t, searchSingleRes[0].IDs.(*entity.ColumnInt64).Data(), vecColumnDefault.IdsColumn.(*entity.ColumnInt64).Data()[0])
   353  
   354  	// search multi partitions
   355  	searchMultiRes, _ := mc.Search(
   356  		ctx, collName,
   357  		[]string{common.DefaultPartition, partitionName},
   358  		"",
   359  		[]string{common.DefaultFloatFieldName},
   360  		[]entity.Vector{
   361  			entity.FloatVector(vecDefaultData),
   362  			entity.FloatVector(vecPartitionData),
   363  		},
   364  		common.DefaultFloatVecFieldName,
   365  		entity.L2,
   366  		common.DefaultTopK,
   367  		sp,
   368  	)
   369  	common.CheckSearchResult(t, searchMultiRes, 2, common.DefaultTopK)
   370  	require.Contains(t, searchMultiRes[0].IDs.(*entity.ColumnInt64).Data(), vecColumnDefault.IdsColumn.(*entity.ColumnInt64).Data()[0])
   371  	require.Contains(t, searchMultiRes[1].IDs.(*entity.ColumnInt64).Data(), vecColumnPartition.IdsColumn.(*entity.ColumnInt64).Data()[0])
   372  }
   373  
   374  // test search empty output fields []string{} -> [], []string{""}
   375  func TestSearchEmptyOutputFields(t *testing.T) {
   376  	t.Parallel()
   377  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   378  	// connect
   379  	mc := createMilvusClient(ctx, t)
   380  
   381  	for _, enableDynamic := range []bool{true, false} {
   382  		// create collection with data
   383  		collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, true, client.WithEnableDynamicSchema(enableDynamic))
   384  
   385  		// load collection
   386  		errLoad := mc.LoadCollection(ctx, collName, false)
   387  		common.CheckErr(t, errLoad, true)
   388  
   389  		// search vector output fields []string{} -> []
   390  		sp, _ := entity.NewIndexHNSWSearchParam(74)
   391  		searchResPkOutput, errSearch := mc.Search(
   392  			ctx, collName,
   393  			[]string{},
   394  			"",
   395  			[]string{},
   396  			common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   397  			common.DefaultFloatVecFieldName,
   398  			entity.L2,
   399  			common.DefaultTopK,
   400  			sp,
   401  		)
   402  		common.CheckErr(t, errSearch, true)
   403  		common.CheckOutputFields(t, searchResPkOutput[0].Fields, []string{})
   404  		common.CheckSearchResult(t, searchResPkOutput, common.DefaultNq, common.DefaultTopK)
   405  
   406  		// search vector output fields []string{""}
   407  		res, errSearchExist := mc.Search(
   408  			ctx, collName,
   409  			[]string{},
   410  			"",
   411  			[]string{"a"},
   412  			common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   413  			common.DefaultFloatVecFieldName,
   414  			entity.L2,
   415  			common.DefaultTopK,
   416  			sp,
   417  		)
   418  
   419  		if enableDynamic {
   420  			common.CheckErr(t, errSearchExist, true)
   421  			common.CheckOutputFields(t, res[0].Fields, []string{"a"})
   422  		} else {
   423  			common.CheckErr(t, errSearchExist, false, "not exist")
   424  		}
   425  		common.CheckSearchResult(t, searchResPkOutput, common.DefaultNq, common.DefaultTopK)
   426  	}
   427  }
   428  
   429  // test search output fields not exist -> output existed fields
   430  func TestSearchNotExistOutputFields(t *testing.T) {
   431  	t.Parallel()
   432  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   433  	// connect
   434  	mc := createMilvusClient(ctx, t)
   435  
   436  	for _, enableDynamic := range []bool{false, true} {
   437  		// create collection with data
   438  		collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, true, client.WithEnableDynamicSchema(enableDynamic))
   439  
   440  		// load collection
   441  		errLoad := mc.LoadCollection(ctx, collName, false)
   442  		common.CheckErr(t, errLoad, true)
   443  
   444  		type notExistOutputFields []string
   445  
   446  		// search vector output fields not exist, part exist
   447  		outputFields := []notExistOutputFields{[]string{"aaa"}, []string{"fields", common.DefaultFloatFieldName},
   448  			[]string{"fields", "*"}}
   449  		sp, _ := entity.NewIndexHNSWSearchParam(74)
   450  		for _, fields := range outputFields {
   451  			log.Println(fields)
   452  			_, errSearch := mc.Search(
   453  				ctx, collName,
   454  				[]string{},
   455  				"",
   456  				fields,
   457  				common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   458  				common.DefaultFloatVecFieldName,
   459  				entity.L2,
   460  				common.DefaultTopK,
   461  				sp,
   462  			)
   463  			if enableDynamic {
   464  				common.CheckErr(t, errSearch, true)
   465  			} else {
   466  				common.CheckErr(t, errSearch, false, "not exist")
   467  			}
   468  		}
   469  	}
   470  }
   471  
   472  // test search output fields only pk
   473  func TestSearchOutputFields(t *testing.T) {
   474  	t.Parallel()
   475  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   476  	// connect
   477  	mc := createMilvusClient(ctx, t)
   478  
   479  	for _, enableDynamic := range []bool{true, false} {
   480  		// create collection
   481  		cp := CollectionParams{CollectionFieldsType: VarcharBinaryVec, AutoID: false, EnableDynamicField: enableDynamic,
   482  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
   483  		collName := createCollection(ctx, t, mc, cp)
   484  
   485  		// insert
   486  		dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: VarcharBinaryVec,
   487  			start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: enableDynamic}
   488  		_, _ = insertData(ctx, t, mc, dp)
   489  		mc.Flush(ctx, collName, false)
   490  
   491  		// index
   492  		idx, _ := entity.NewIndexBinIvfFlat(entity.JACCARD, 128)
   493  		err := mc.CreateIndex(ctx, collName, common.DefaultBinaryVecFieldName, idx, false, client.WithIndexName(""))
   494  		common.CheckErr(t, err, true)
   495  
   496  		// load collection
   497  		errLoad := mc.LoadCollection(ctx, collName, false)
   498  		common.CheckErr(t, errLoad, true)
   499  
   500  		// search vector output fields not exist
   501  		outputFields := []string{common.DefaultVarcharFieldName, common.DefaultBinaryVecFieldName}
   502  		if enableDynamic {
   503  			outputFields = append(outputFields, common.DefaultDynamicFieldName)
   504  		}
   505  		sp, _ := entity.NewIndexBinIvfFlatSearchParam(64)
   506  		searchRes, _ := mc.Search(
   507  			ctx, collName,
   508  			[]string{},
   509  			"",
   510  			outputFields,
   511  			common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeBinaryVector),
   512  			common.DefaultBinaryVecFieldName,
   513  			entity.JACCARD,
   514  			common.DefaultTopK,
   515  			sp,
   516  		)
   517  		common.CheckOutputFields(t, searchRes[0].Fields, outputFields)
   518  		common.CheckSearchResult(t, searchRes, common.DefaultNq, common.DefaultTopK)
   519  	}
   520  }
   521  
   522  // test search output all * fields when enable dynamic and insert dynamic column data
   523  func TestSearchOutputAllFields(t *testing.T) {
   524  	t.Parallel()
   525  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   526  	// connect
   527  	mc := createMilvusClient(ctx, t)
   528  
   529  	for _, enableDynamic := range []bool{false, true} {
   530  		// create collection
   531  		cp := CollectionParams{CollectionFieldsType: AllFields, AutoID: false, EnableDynamicField: enableDynamic,
   532  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
   533  		collName := createCollection(ctx, t, mc, cp)
   534  
   535  		// insert
   536  		dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: AllFields,
   537  			start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: enableDynamic}
   538  		_, _ = insertData(ctx, t, mc, dp)
   539  		_ = mc.Flush(ctx, collName, false)
   540  
   541  		// create index
   542  		indexHnsw, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
   543  		indexBinary, _ := entity.NewIndexBinIvfFlat(entity.JACCARD, 64)
   544  		for _, fieldName := range common.AllVectorsFieldsName {
   545  			if fieldName == common.DefaultBinaryVecFieldName {
   546  				mc.CreateIndex(ctx, collName, fieldName, indexBinary, false)
   547  			} else {
   548  				mc.CreateIndex(ctx, collName, fieldName, indexHnsw, false)
   549  			}
   550  		}
   551  
   552  		// Load collection
   553  		errLoad := mc.LoadCollection(ctx, collName, false)
   554  		common.CheckErr(t, errLoad, true)
   555  
   556  		// search vector output all scalar fields
   557  		queryVec := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector)
   558  		allFields := common.GetAllFieldsName(enableDynamic, false)
   559  		sp, _ := entity.NewIndexHNSWSearchParam(74)
   560  		searchRes, _ := mc.Search(ctx, collName, []string{},
   561  			"",
   562  			[]string{"*"},
   563  			queryVec,
   564  			common.DefaultFloatVecFieldName,
   565  			entity.L2,
   566  			common.DefaultTopK,
   567  			sp,
   568  		)
   569  		common.CheckOutputFields(t, searchRes[0].Fields, allFields)
   570  
   571  		// search with output * fields
   572  		if enableDynamic {
   573  			//search output [*, a] fields -> output all fields, no a field
   574  			_, errNotExist := mc.Search(ctx, collName, []string{}, "", []string{"*", "a"}, queryVec,
   575  				common.DefaultFloatVecFieldName, entity.L2, common.DefaultTopK, sp)
   576  			common.CheckErr(t, errNotExist, true)
   577  			common.CheckOutputFields(t, searchRes[0].Fields, allFields)
   578  
   579  			//search output [*, dynamicNumber] fields -> -> output all fields, $meta replace by dynamicNumber
   580  			searchRes, _ = mc.Search(ctx, collName, []string{}, "", []string{"*", common.DefaultDynamicNumberField},
   581  				queryVec, common.DefaultFloatVecFieldName, entity.L2, common.DefaultTopK, sp)
   582  			common.CheckOutputFields(t, searchRes[0].Fields, append(allFields, common.DefaultDynamicNumberField))
   583  
   584  			///search output [*, dynamicNumber] fields -> -> output all fields, $meta replace by dynamicNumber
   585  			searchRes, _ = mc.Search(ctx, collName, []string{}, "", []string{common.DefaultDynamicNumberField},
   586  				queryVec, common.DefaultFloatVecFieldName, entity.L2, common.DefaultTopK, sp)
   587  			common.CheckOutputFields(t, searchRes[0].Fields, []string{common.DefaultDynamicNumberField})
   588  		}
   589  	}
   590  }
   591  
   592  // test search with invalid vector field name: not exist; non-vector field, empty fiend name, json and dynamic field -> error
   593  func TestSearchInvalidVectorField(t *testing.T) {
   594  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   595  	// connect
   596  	mc := createMilvusClient(ctx, t)
   597  
   598  	// create collection with data
   599  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, true)
   600  
   601  	// load collection
   602  	errLoad := mc.LoadCollection(ctx, collName, false)
   603  	common.CheckErr(t, errLoad, true)
   604  
   605  	type invalidVectorFieldStruct struct {
   606  		vectorField string
   607  		errNil      bool
   608  		errMsg      string
   609  	}
   610  
   611  	invalidVectorFields := []invalidVectorFieldStruct{
   612  		// not exist field
   613  		{vectorField: common.DefaultBinaryVecFieldName, errNil: false, errMsg: fmt.Sprintf("failed to get field schema by name: fieldName(%s) not found", common.DefaultBinaryVecFieldName)},
   614  
   615  		// non-vector field
   616  		{vectorField: common.DefaultIntFieldName, errNil: false, errMsg: fmt.Sprintf("failed to create query plan: field (%s) to search is not of vector data type", common.DefaultIntFieldName)},
   617  
   618  		// json field
   619  		{vectorField: common.DefaultJSONFieldName, errNil: false, errMsg: fmt.Sprintf("failed to get field schema by name: fieldName(%s) not found", common.DefaultJSONFieldName)},
   620  
   621  		// dynamic field
   622  		{vectorField: common.DefaultDynamicFieldName, errNil: false, errMsg: fmt.Sprintf("failed to get field schema by name: fieldName(%s) not found", common.DefaultDynamicFieldName)},
   623  
   624  		// allows empty vector field name
   625  		{vectorField: "", errNil: true, errMsg: ""},
   626  	}
   627  
   628  	sp, _ := entity.NewIndexHNSWSearchParam(74)
   629  	for _, invalidVectorField := range invalidVectorFields {
   630  		t.Run(invalidVectorField.vectorField, func(t *testing.T) {
   631  			_, errSearchNotExist := mc.Search(
   632  				ctx, collName,
   633  				[]string{},
   634  				"",
   635  				[]string{common.DefaultIntFieldName},
   636  				common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   637  				invalidVectorField.vectorField,
   638  				entity.L2,
   639  				common.DefaultTopK,
   640  				sp,
   641  			)
   642  			common.CheckErr(t, errSearchNotExist, invalidVectorField.errNil, invalidVectorField.errMsg)
   643  		})
   644  	}
   645  }
   646  
   647  // test search with invalid vectors
   648  func TestSearchInvalidVectors(t *testing.T) {
   649  	t.Parallel()
   650  	ctx := createContext(t, time.Second*common.DefaultTimeout*2)
   651  	// connect
   652  	mc := createMilvusClient(ctx, t)
   653  
   654  	// create collection with data
   655  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, true)
   656  
   657  	// load collection
   658  	errLoad := mc.LoadCollection(ctx, collName, false)
   659  	common.CheckErr(t, errLoad, true)
   660  
   661  	type invalidVectorsStruct struct {
   662  		vectors []entity.Vector
   663  		errMsg  string
   664  	}
   665  
   666  	invalidVectors := []invalidVectorsStruct{
   667  		// dim not match
   668  		{vectors: common.GenSearchVectors(common.DefaultNq, 64, entity.FieldTypeFloatVector), errMsg: "vector dimension mismatch"},
   669  
   670  		//vector type not match
   671  		{vectors: common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeBinaryVector), errMsg: "vector type must be the same"},
   672  
   673  		// empty vectors
   674  		{vectors: []entity.Vector{}, errMsg: "nq [0] is invalid"},
   675  		{vectors: []entity.Vector{entity.FloatVector{}}, errMsg: "vector dimension mismatch"},
   676  	}
   677  
   678  	sp, _ := entity.NewIndexHNSWSearchParam(74)
   679  	for _, invalidVector := range invalidVectors {
   680  		// search vectors empty slice
   681  		_, errSearchEmpty := mc.Search(
   682  			ctx, collName,
   683  			[]string{},
   684  			"",
   685  			[]string{"*"},
   686  			invalidVector.vectors,
   687  			common.DefaultFloatVecFieldName,
   688  			entity.L2,
   689  			common.DefaultTopK,
   690  			sp,
   691  		)
   692  		common.CheckErr(t, errSearchEmpty, false, invalidVector.errMsg)
   693  	}
   694  }
   695  
   696  // test search with invalid vectors
   697  func TestSearchInvalidVectorsEmptyCollection(t *testing.T) {
   698  	t.Skip("https://github.com/milvus-io/milvus/issues/33639")
   699  	t.Skip("https://github.com/milvus-io/milvus/issues/33637")
   700  	t.Parallel()
   701  	ctx := createContext(t, time.Second*common.DefaultTimeout*2)
   702  	// connect
   703  	mc := createMilvusClient(ctx, t)
   704  
   705  	// create collection with data
   706  	collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards)
   707  
   708  	// index
   709  	idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
   710  	err := mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false, client.WithIndexName(""))
   711  	common.CheckErr(t, err, true)
   712  
   713  	// load collection
   714  	errLoad := mc.LoadCollection(ctx, collName, false)
   715  	common.CheckErr(t, errLoad, true)
   716  
   717  	type invalidVectorsStruct struct {
   718  		vectors []entity.Vector
   719  		errMsg  string
   720  	}
   721  
   722  	invalidVectors := []invalidVectorsStruct{
   723  		// dim not match
   724  		{vectors: common.GenSearchVectors(common.DefaultNq, 64, entity.FieldTypeFloatVector), errMsg: "vector dimension mismatch"},
   725  
   726  		//vector type not match
   727  		{vectors: common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeBinaryVector), errMsg: "vector type must be the same"},
   728  
   729  		// empty vectors
   730  		{vectors: []entity.Vector{}, errMsg: "nq [0] is invalid"},
   731  		{vectors: []entity.Vector{entity.FloatVector{}}, errMsg: "vector dimension mismatch"},
   732  	}
   733  
   734  	sp, _ := entity.NewIndexHNSWSearchParam(74)
   735  	for _, invalidVector := range invalidVectors {
   736  		// search vectors empty slice
   737  		_, errSearchEmpty := mc.Search(ctx, collName, []string{}, "", []string{"*"}, invalidVector.vectors,
   738  			common.DefaultFloatVecFieldName, entity.L2, common.DefaultTopK, sp)
   739  		common.CheckErr(t, errSearchEmpty, false, invalidVector.errMsg)
   740  	}
   741  }
   742  
   743  // test search metric type isn't the same with index metric type
   744  func TestSearchNotMatchMetricType(t *testing.T) {
   745  	ctx := createContext(t, time.Second*common.DefaultTimeout*2)
   746  	// connect
   747  	mc := createMilvusClient(ctx, t)
   748  
   749  	// create collection with data
   750  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, true)
   751  
   752  	// load collection
   753  	errLoad := mc.LoadCollection(ctx, collName, false)
   754  	common.CheckErr(t, errLoad, true)
   755  
   756  	sp, _ := entity.NewIndexHNSWSearchParam(74)
   757  	_, errSearchEmpty := mc.Search(
   758  		ctx, collName,
   759  		[]string{},
   760  		"",
   761  		[]string{common.DefaultIntFieldName},
   762  		common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   763  		common.DefaultFloatVecFieldName,
   764  		entity.IP,
   765  		common.DefaultTopK,
   766  		sp,
   767  	)
   768  	common.CheckErr(t, errSearchEmpty, false, "invalid parameter")
   769  }
   770  
   771  // test search with invalid topK -> error
   772  func TestSearchInvalidTopK(t *testing.T) {
   773  	ctx := createContext(t, time.Second*common.DefaultTimeout*2)
   774  	// connect
   775  	mc := createMilvusClient(ctx, t)
   776  
   777  	// create collection with data
   778  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, false)
   779  
   780  	// create ivf sq8 index
   781  	idx, _ := entity.NewIndexIvfFlat(entity.L2, 128)
   782  	err := mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false, client.WithIndexName(""))
   783  	common.CheckErr(t, err, true)
   784  
   785  	// load collection
   786  	errLoad := mc.LoadCollection(ctx, collName, false)
   787  	common.CheckErr(t, errLoad, true)
   788  
   789  	invalidTopKs := []int{-1, 0, 16385}
   790  
   791  	sp, _ := entity.NewIndexIvfSQ8SearchParam(64)
   792  
   793  	for _, invalidTopK := range invalidTopKs {
   794  		_, errSearchEmpty := mc.Search(
   795  			ctx, collName,
   796  			[]string{},
   797  			"",
   798  			[]string{common.DefaultIntFieldName},
   799  			common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   800  			common.DefaultFloatVecFieldName,
   801  			entity.L2,
   802  			invalidTopK,
   803  			sp,
   804  		)
   805  		common.CheckErr(t, errSearchEmpty, false, "should be in range [1, 16384]")
   806  	}
   807  }
   808  
   809  // test search with invalid search params
   810  func TestSearchInvalidSearchParams(t *testing.T) {
   811  
   812  	// ivf flat search params nlist [1, 65536], nprobe [1, nlist]
   813  	invalidNprobe := []int{-1, 0, 65537}
   814  	for _, nprobe := range invalidNprobe {
   815  		_, errIvfFlat := entity.NewIndexIvfFlatSearchParam(nprobe)
   816  		common.CheckErr(t, errIvfFlat, false, "nprobe has to be in range [1, 65536]")
   817  	}
   818  
   819  	// ivf sq8 search param
   820  	for _, nprobe := range invalidNprobe {
   821  		_, errIvfSq8 := entity.NewIndexIvfSQ8SearchParam(nprobe)
   822  		log.Println(nprobe)
   823  		common.CheckErr(t, errIvfSq8, false, "nprobe has to be in range [1, 65536]")
   824  	}
   825  
   826  	// ivf pq search param
   827  	for _, nprobe := range invalidNprobe {
   828  		_, errIvfPq := entity.NewIndexIvfPQSearchParam(nprobe)
   829  		common.CheckErr(t, errIvfPq, false, "nprobe has to be in range [1, 65536]")
   830  	}
   831  
   832  	// hnsw search params ef [top_k, 32768]
   833  	invalidEfs := []int{-1, 0, 32769}
   834  	for _, invalidEf := range invalidEfs {
   835  		_, errHnsw := entity.NewIndexHNSWSearchParam(invalidEf)
   836  		common.CheckErr(t, errHnsw, false, "ef has to be in range [1, 32768]")
   837  	}
   838  
   839  	// bin ivf flat
   840  	for _, nprobe := range invalidNprobe {
   841  		_, errBinIvfFlat := entity.NewIndexBinIvfFlatSearchParam(nprobe)
   842  		common.CheckErr(t, errBinIvfFlat, false, "nprobe has to be in range [1, 65536]")
   843  	}
   844  
   845  	// scann index invalid nprobe
   846  	for _, nprobe := range invalidNprobe {
   847  		_, errScann := entity.NewIndexSCANNSearchParam(nprobe, 100)
   848  		common.CheckErr(t, errScann, false, "nprobe has to be in range [1, 65536]")
   849  	}
   850  
   851  	_, errScann := entity.NewIndexSCANNSearchParam(16, 0)
   852  	common.CheckErr(t, errScann, false, "reorder_k has to be in range [1, 9223372036854775807]")
   853  }
   854  
   855  // search with index hnsw search param ef < topK -> error
   856  func TestSearchEfHnsw(t *testing.T) {
   857  	ctx := createContext(t, time.Second*common.DefaultTimeout*2)
   858  	// connect
   859  	mc := createMilvusClient(ctx, t)
   860  
   861  	// create collection with data
   862  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, true)
   863  
   864  	// load collection
   865  	errLoad := mc.LoadCollection(ctx, collName, false)
   866  	common.CheckErr(t, errLoad, true)
   867  
   868  	// ef [top_k, 32768]
   869  	sp, _ := entity.NewIndexHNSWSearchParam(7)
   870  	_, errSearchEmpty := mc.Search(
   871  		ctx, collName,
   872  		[]string{},
   873  		"",
   874  		[]string{common.DefaultIntFieldName},
   875  		common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   876  		common.DefaultFloatVecFieldName,
   877  		entity.L2,
   878  		common.DefaultTopK,
   879  		sp,
   880  	)
   881  	common.CheckErr(t, errSearchEmpty, false, "ef(7) should be larger than k(10)")
   882  }
   883  
   884  // test search params mismatch index type, hnsw index and ivf sq8 search param -> search with default hnsw params, ef=topK
   885  func TestSearchSearchParamsMismatchIndex(t *testing.T) {
   886  	ctx := createContext(t, time.Second*common.DefaultTimeout*2)
   887  	// connect
   888  	mc := createMilvusClient(ctx, t)
   889  
   890  	// create collection with data and create hnsw index
   891  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, true)
   892  
   893  	// load collection
   894  	errLoad := mc.LoadCollection(ctx, collName, false)
   895  	common.CheckErr(t, errLoad, true)
   896  
   897  	// ef [top_k, 32768]
   898  	sp, _ := entity.NewIndexIvfSQ8SearchParam(64)
   899  	resSearch, errSearch := mc.Search(
   900  		ctx, collName,
   901  		[]string{},
   902  		"",
   903  		[]string{common.DefaultIntFieldName},
   904  		common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   905  		common.DefaultFloatVecFieldName,
   906  		entity.L2,
   907  		common.DefaultTopK,
   908  		sp,
   909  	)
   910  	common.CheckErr(t, errSearch, true)
   911  	common.CheckSearchResult(t, resSearch, common.DefaultNq, common.DefaultTopK)
   912  }
   913  
   914  // test search with valid expression
   915  func TestSearchExpr(t *testing.T) {
   916  	ctx := createContext(t, time.Second*common.DefaultTimeout*2)
   917  	// connect
   918  	mc := createMilvusClient(ctx, t)
   919  
   920  	// create collection with data
   921  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, true)
   922  
   923  	// load collection
   924  	errLoad := mc.LoadCollection(ctx, collName, false)
   925  	common.CheckErr(t, errLoad, true)
   926  
   927  	// search vector with expr: int64 < 1000
   928  	sp, _ := entity.NewIndexHNSWSearchParam(74)
   929  	searchResult, errSearch := mc.Search(
   930  		ctx, collName,
   931  		[]string{common.DefaultPartition},
   932  		fmt.Sprintf("%s < 1000", common.DefaultFloatFieldName),
   933  		[]string{common.DefaultFloatFieldName},
   934  		common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
   935  		common.DefaultFloatVecFieldName,
   936  		entity.L2,
   937  		common.DefaultTopK,
   938  		sp,
   939  	)
   940  	common.CheckErr(t, errSearch, true)
   941  	// check search ids less than 1000
   942  	common.CheckSearchResult(t, searchResult, common.DefaultNq, common.DefaultTopK)
   943  	for _, res := range searchResult {
   944  		for _, id := range res.IDs.(*entity.ColumnInt64).Data() {
   945  			require.Less(t, id, int64(1000))
   946  		}
   947  	}
   948  
   949  	// search vector with expr: float in [1.0]
   950  	searchResult2, errSearch2 := mc.Search(
   951  		ctx, collName,
   952  		[]string{common.DefaultPartition},
   953  		fmt.Sprintf("%s in [1.0]", common.DefaultFloatFieldName),
   954  		[]string{common.DefaultFloatFieldName},
   955  		common.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeFloatVector),
   956  		common.DefaultFloatVecFieldName,
   957  		entity.L2,
   958  		2,
   959  		sp,
   960  	)
   961  	common.CheckErr(t, errSearch2, true)
   962  	// check search ids equal to 1
   963  	common.CheckSearchResult(t, searchResult2, 1, 1)
   964  	require.Equal(t, searchResult2[0].IDs.(*entity.ColumnInt64).Data()[0], int64(1))
   965  }
   966  
   967  // test search with invalid expression
   968  func TestSearchInvalidExpr(t *testing.T) {
   969  	t.Parallel()
   970  
   971  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   972  	// connect
   973  	mc := createMilvusClient(ctx, t)
   974  
   975  	// create collection
   976  	cp := CollectionParams{CollectionFieldsType: Int64FloatVecJSON, AutoID: false, EnableDynamicField: true,
   977  		ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
   978  	collName := createCollection(ctx, t, mc, cp)
   979  
   980  	// insert
   981  	dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: Int64FloatVecJSON,
   982  		start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true}
   983  	_, _ = insertData(ctx, t, mc, dp)
   984  
   985  	idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
   986  	_ = mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false)
   987  
   988  	// Load collection
   989  	errLoad := mc.LoadCollection(ctx, collName, false)
   990  	common.CheckErr(t, errLoad, true)
   991  
   992  	// search with invalid expr
   993  	sp, _ := entity.NewIndexHNSWSearchParam(74)
   994  	for _, exprStruct := range common.InvalidExpressions {
   995  		_, errSearchEmpty := mc.Search(
   996  			ctx, collName,
   997  			[]string{},
   998  			exprStruct.Expr,
   999  			[]string{common.DefaultIntFieldName},
  1000  			common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
  1001  			common.DefaultFloatVecFieldName,
  1002  			entity.L2,
  1003  			common.DefaultTopK,
  1004  			sp,
  1005  		)
  1006  		common.CheckErr(t, errSearchEmpty, exprStruct.ErrNil, exprStruct.ErrMsg)
  1007  	}
  1008  }
  1009  
  1010  func TestSearchJsonFieldExpr(t *testing.T) {
  1011  	t.Parallel()
  1012  
  1013  	ctx := createContext(t, time.Second*common.DefaultTimeout)
  1014  	// connect
  1015  	mc := createMilvusClient(ctx, t)
  1016  
  1017  	for _, dynamicField := range []bool{false} {
  1018  		// create collection
  1019  		cp := CollectionParams{CollectionFieldsType: Int64FloatVecJSON, AutoID: false, EnableDynamicField: dynamicField,
  1020  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
  1021  		collName := createCollection(ctx, t, mc, cp)
  1022  
  1023  		// insert
  1024  		dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: Int64FloatVecJSON,
  1025  			start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: dynamicField}
  1026  		_, _ = insertData(ctx, t, mc, dp)
  1027  		mc.Flush(ctx, collName, false)
  1028  
  1029  		idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
  1030  		_ = mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false)
  1031  
  1032  		// Load collection
  1033  		errLoad := mc.LoadCollection(ctx, collName, false)
  1034  		common.CheckErr(t, errLoad, true)
  1035  
  1036  		exprs := []string{
  1037  			"",
  1038  			fmt.Sprintf("exists %s['number'] ", common.DefaultJSONFieldName),   // exists
  1039  			"json[\"number\"] > 1 and json[\"number\"] < 1000",                 // > and
  1040  			fmt.Sprintf("%s[\"number\"] > 10", common.DefaultJSONFieldName),    // number >
  1041  			fmt.Sprintf("%s != 10 ", common.DefaultJSONFieldName),              // json != 10
  1042  			fmt.Sprintf("%s[\"number\"] < 2000", common.DefaultJSONFieldName),  // number <
  1043  			fmt.Sprintf("%s[\"bool\"] != true", common.DefaultJSONFieldName),   // bool !=
  1044  			fmt.Sprintf("%s[\"bool\"] == False", common.DefaultJSONFieldName),  // bool ==
  1045  			fmt.Sprintf("%s[\"bool\"] in [true]", common.DefaultJSONFieldName), // bool in
  1046  			fmt.Sprintf("%s[\"string\"] >= '1' ", common.DefaultJSONFieldName), // string >=
  1047  			fmt.Sprintf("%s['list'][0] > 200", common.DefaultJSONFieldName),    // list filter
  1048  			fmt.Sprintf("%s['list'] != [2, 3]", common.DefaultJSONFieldName),   // json[list] !=
  1049  			fmt.Sprintf("%s > 2000", common.DefaultJSONFieldName),              // json > 2000
  1050  			fmt.Sprintf("%s like '2%%' ", common.DefaultJSONFieldName),         // json like '2%'
  1051  			fmt.Sprintf("%s[0] > 2000 ", common.DefaultJSONFieldName),          // json[0] > 2000
  1052  			fmt.Sprintf("%s > 2000.5 ", common.DefaultJSONFieldName),           // json > 2000.5
  1053  		}
  1054  
  1055  		// search with jsonField expr key datatype and json data type mismatch
  1056  		sp, _ := entity.NewIndexHNSWSearchParam(74)
  1057  		for _, expr := range exprs {
  1058  			log.Printf("search expr: %s", expr)
  1059  			searchRes, errSearchEmpty := mc.Search(
  1060  				ctx, collName,
  1061  				[]string{},
  1062  				expr,
  1063  				[]string{common.DefaultIntFieldName, common.DefaultJSONFieldName},
  1064  				common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
  1065  				common.DefaultFloatVecFieldName,
  1066  				entity.L2,
  1067  				common.DefaultTopK,
  1068  				sp,
  1069  			)
  1070  			common.CheckErr(t, errSearchEmpty, true)
  1071  			common.CheckOutputFields(t, searchRes[0].Fields, []string{common.DefaultIntFieldName, common.DefaultJSONFieldName})
  1072  			common.CheckSearchResult(t, searchRes, common.DefaultNq, common.DefaultTopK)
  1073  		}
  1074  	}
  1075  }
  1076  
  1077  // search dynamic field with expr
  1078  func TestSearchDynamicFieldExpr(t *testing.T) {
  1079  	t.Parallel()
  1080  
  1081  	ctx := createContext(t, time.Second*common.DefaultTimeout)
  1082  	// connect
  1083  	mc := createMilvusClient(ctx, t)
  1084  
  1085  	for _, withRows := range []bool{true, false} {
  1086  		// create collection
  1087  		cp := CollectionParams{CollectionFieldsType: Int64FloatVecJSON, AutoID: false, EnableDynamicField: true,
  1088  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
  1089  		collName := createCollection(ctx, t, mc, cp)
  1090  
  1091  		// insert
  1092  		dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: Int64FloatVecJSON,
  1093  			start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true, WithRows: withRows}
  1094  		_, _ = insertData(ctx, t, mc, dp)
  1095  		mc.Flush(ctx, collName, false)
  1096  
  1097  		idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
  1098  		_ = mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false)
  1099  
  1100  		// Load collection
  1101  		errLoad := mc.LoadCollection(ctx, collName, false)
  1102  		common.CheckErr(t, errLoad, true)
  1103  
  1104  		exprs := []string{
  1105  			"",
  1106  			"exists dynamicNumber", // exist without dynamic fieldName
  1107  			fmt.Sprintf("exists %s[\"dynamicNumber\"]", common.DefaultDynamicFieldName), // exist with fieldName
  1108  			fmt.Sprintf("%s[\"dynamicNumber\"] > 10", common.DefaultDynamicFieldName),   // int expr with fieldName
  1109  			fmt.Sprintf("%s[\"dynamicBool\"] == true", common.DefaultDynamicFieldName),  // bool with fieldName
  1110  			"dynamicBool == False", // bool without fieldName
  1111  			fmt.Sprintf("%s['dynamicString'] == '1'", common.DefaultDynamicFieldName), // string with fieldName
  1112  			"dynamicString != \"2\" ", // string without fieldName
  1113  		}
  1114  
  1115  		// search with jsonField expr key datatype and json data type mismatch
  1116  		sp, _ := entity.NewIndexHNSWSearchParam(74)
  1117  		for _, expr := range exprs {
  1118  			log.Print(expr)
  1119  			searchRes, errSearchEmpty := mc.Search(
  1120  				ctx, collName,
  1121  				[]string{},
  1122  				expr,
  1123  				[]string{common.DefaultIntFieldName, "dynamicNumber", "number"},
  1124  				common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
  1125  				common.DefaultFloatVecFieldName,
  1126  				entity.L2,
  1127  				common.DefaultTopK,
  1128  				sp,
  1129  			)
  1130  			common.CheckErr(t, errSearchEmpty, true)
  1131  			common.CheckOutputFields(t, searchRes[0].Fields, []string{common.DefaultIntFieldName, "dynamicNumber", "number"})
  1132  			if expr == "$meta['dynamicString'] == '1'" {
  1133  				common.CheckSearchResult(t, searchRes, common.DefaultNq, 1)
  1134  			} else {
  1135  				common.CheckSearchResult(t, searchRes, common.DefaultNq, common.DefaultTopK)
  1136  			}
  1137  		}
  1138  
  1139  		// search with expr filter number and, &&, or, ||
  1140  		exprs2 := []string{
  1141  			"dynamicNumber > 1 and dynamicNumber <= 999", // int expr without fieldName
  1142  			fmt.Sprintf("%s['dynamicNumber'] > 1 && %s['dynamicNumber'] < 1000", common.DefaultDynamicFieldName, common.DefaultDynamicFieldName),
  1143  			"dynamicNumber < 888 || dynamicNumber < 1000",
  1144  			fmt.Sprintf("%s['dynamicNumber'] < 888 or %s['dynamicNumber'] < 1000", common.DefaultDynamicFieldName, common.DefaultDynamicFieldName),
  1145  			fmt.Sprintf("%s[\"dynamicNumber\"] < 1000", common.DefaultDynamicFieldName), // int expr with fieldName
  1146  		}
  1147  
  1148  		// search
  1149  		for _, expr := range exprs2 {
  1150  			log.Print(expr)
  1151  			searchRes, errSearchEmpty := mc.Search(
  1152  				ctx, collName,
  1153  				[]string{},
  1154  				expr,
  1155  				[]string{common.DefaultIntFieldName, common.DefaultJSONFieldName, common.DefaultDynamicFieldName, "dynamicNumber", "number"},
  1156  				common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
  1157  				common.DefaultFloatVecFieldName,
  1158  				entity.L2,
  1159  				common.DefaultTopK,
  1160  				sp,
  1161  			)
  1162  			common.CheckErr(t, errSearchEmpty, true)
  1163  			common.CheckOutputFields(t, searchRes[0].Fields, []string{common.DefaultIntFieldName, common.DefaultJSONFieldName, common.DefaultDynamicFieldName, "dynamicNumber", "number"})
  1164  			for _, res := range searchRes {
  1165  				for _, id := range res.IDs.(*entity.ColumnInt64).Data() {
  1166  					require.Less(t, id, int64(1000))
  1167  				}
  1168  			}
  1169  		}
  1170  	}
  1171  }
  1172  
  1173  func TestSearchArrayFieldExpr(t *testing.T) {
  1174  	t.Parallel()
  1175  
  1176  	ctx := createContext(t, time.Second*common.DefaultTimeout)
  1177  	// connect
  1178  	mc := createMilvusClient(ctx, t)
  1179  	var capacity int64 = common.TestCapacity
  1180  
  1181  	for _, withRows := range []bool{true, false} {
  1182  		// create collection
  1183  		cp := CollectionParams{CollectionFieldsType: Int64FloatVecArray, AutoID: false, EnableDynamicField: true,
  1184  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim, MaxCapacity: capacity}
  1185  		collName := createCollection(ctx, t, mc, cp, client.WithConsistencyLevel(entity.ClStrong))
  1186  
  1187  		// prepare and insert data
  1188  		dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: Int64FloatVecArray,
  1189  			start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true, WithRows: withRows}
  1190  		_, _ = insertData(ctx, t, mc, dp, common.WithArrayCapacity(capacity))
  1191  		mc.Flush(ctx, collName, false)
  1192  
  1193  		idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
  1194  		_ = mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false)
  1195  
  1196  		// Load collection
  1197  		errLoad := mc.LoadCollection(ctx, collName, false)
  1198  		common.CheckErr(t, errLoad, true)
  1199  
  1200  		exprs := []string{
  1201  			fmt.Sprintf("%s[0] == false", common.DefaultBoolArrayField),                            // array[0] ==
  1202  			fmt.Sprintf("%s[0] > 0", common.DefaultInt64ArrayField),                                // array[0] >
  1203  			fmt.Sprintf("json_contains (%s, %d)", common.DefaultInt16ArrayField, capacity),         // json_contains
  1204  			fmt.Sprintf("array_contains (%s, %d)", common.DefaultInt16ArrayField, capacity),        // array_contains
  1205  			fmt.Sprintf("json_contains_all (%s, [90, 91])", common.DefaultInt64ArrayField),         // json_contains_all
  1206  			fmt.Sprintf("array_contains_all (%s, [90, 91])", common.DefaultInt64ArrayField),        // array_contains_all
  1207  			fmt.Sprintf("array_contains_any (%s, [0, 100, 10000])", common.DefaultFloatArrayField), // array_contains_any
  1208  			fmt.Sprintf("json_contains_any (%s, [0, 100, 10])", common.DefaultFloatArrayField),     // json_contains_any
  1209  			fmt.Sprintf("array_length(%s) == %d", common.DefaultDoubleArrayField, capacity),        // array_length
  1210  		}
  1211  
  1212  		// search with jsonField expr key datatype and json data type mismatch
  1213  		sp, _ := entity.NewIndexHNSWSearchParam(74)
  1214  		for _, expr := range exprs {
  1215  			log.Printf("search expr: %s", expr)
  1216  			searchRes, errSearchEmpty := mc.Search(
  1217  				ctx, collName, []string{},
  1218  				expr, common.AllArrayFieldsName,
  1219  				common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
  1220  				common.DefaultFloatVecFieldName, entity.L2,
  1221  				common.DefaultTopK, sp,
  1222  			)
  1223  			common.CheckErr(t, errSearchEmpty, true)
  1224  			common.CheckOutputFields(t, searchRes[0].Fields, common.AllArrayFieldsName)
  1225  			common.CheckSearchResult(t, searchRes, common.DefaultNq, common.DefaultTopK)
  1226  		}
  1227  
  1228  		// search hits empty
  1229  		searchRes, errSearchEmpty := mc.Search(
  1230  			ctx, collName, []string{},
  1231  			fmt.Sprintf("array_contains (%s, 1000000)", common.DefaultInt32ArrayField),
  1232  			common.AllArrayFieldsName,
  1233  			common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
  1234  			common.DefaultFloatVecFieldName, entity.L2, common.DefaultTopK,
  1235  			sp,
  1236  		)
  1237  		common.CheckErr(t, errSearchEmpty, true)
  1238  		require.Len(t, searchRes, common.DefaultNq)
  1239  		for _, resultSet := range searchRes {
  1240  			assert.EqualValues(t, 0, resultSet.ResultCount)
  1241  		}
  1242  	}
  1243  }
  1244  
  1245  // search with index scann search param ef < topK -> error
  1246  func TestSearchInvalidScannReorderK(t *testing.T) {
  1247  	ctx := createContext(t, time.Second*common.DefaultTimeout)
  1248  	// connect
  1249  	mc := createMilvusClient(ctx, t)
  1250  
  1251  	// create collection
  1252  	cp := CollectionParams{CollectionFieldsType: Int64FloatVecJSON, AutoID: false, EnableDynamicField: true,
  1253  		ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
  1254  	collName := createCollection(ctx, t, mc, cp)
  1255  
  1256  	// insert
  1257  	dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: Int64FloatVecJSON,
  1258  		start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true, WithRows: false}
  1259  	_, _ = insertData(ctx, t, mc, dp)
  1260  
  1261  	// flush
  1262  	mc.Flush(ctx, collName, false)
  1263  
  1264  	// create scann index
  1265  	indexScann, _ := entity.NewIndexSCANN(entity.L2, 16, false)
  1266  	err := mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, indexScann, false)
  1267  	common.CheckErr(t, err, true)
  1268  
  1269  	// describe index
  1270  	indexes, _ := mc.DescribeIndex(ctx, collName, common.DefaultFloatVecFieldName)
  1271  	log.Println(indexes)
  1272  	expIndex := entity.NewGenericIndex(common.DefaultFloatVecFieldName, entity.SCANN, indexScann.Params())
  1273  	common.CheckIndexResult(t, indexes, expIndex)
  1274  
  1275  	// load collection
  1276  	errLoad := mc.LoadCollection(ctx, collName, false)
  1277  	common.CheckErr(t, errLoad, true)
  1278  
  1279  	// search with invalid reorder_k < topk
  1280  	queryVec := common.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeFloatVector)
  1281  	spInvalid, _ := entity.NewIndexSCANNSearchParam(8, common.DefaultTopK-1)
  1282  	_, errInvalid := mc.Search(ctx, collName, []string{}, "", []string{common.DefaultIntFieldName}, queryVec,
  1283  		common.DefaultFloatVecFieldName, entity.L2, common.DefaultTopK, spInvalid)
  1284  	common.CheckErr(t, errInvalid, false,
  1285  		fmt.Sprintf("reorder_k(%d) should be larger than k(%d)", common.DefaultTopK-1, common.DefaultTopK))
  1286  
  1287  	// valid scann index search reorder_k
  1288  	sp, _ := entity.NewIndexSCANNSearchParam(8, 20)
  1289  	resSearch, errSearch := mc.Search(ctx, collName, []string{}, "", []string{common.DefaultIntFieldName}, queryVec,
  1290  		common.DefaultFloatVecFieldName, entity.L2, common.DefaultTopK, sp)
  1291  	common.CheckErr(t, errSearch, true)
  1292  	common.CheckSearchResult(t, resSearch, 1, common.DefaultTopK)
  1293  }
  1294  
  1295  // test search with scann index params: with_raw_data and metrics_type [L2, IP, COSINE]
  1296  func TestSearchScannAllMetricsWithRawData(t *testing.T) {
  1297  	t.Parallel()
  1298  	for _, withRawData := range []bool{true, false} {
  1299  		for _, metricType := range []entity.MetricType{entity.L2, entity.IP, entity.COSINE} {
  1300  			ctx := createContext(t, time.Second*common.DefaultTimeout)
  1301  			// connect
  1302  			mc := createMilvusClient(ctx, t)
  1303  
  1304  			// create collection
  1305  			cp := CollectionParams{CollectionFieldsType: Int64FloatVecJSON, AutoID: false, EnableDynamicField: true,
  1306  				ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
  1307  			collName := createCollection(ctx, t, mc, cp)
  1308  
  1309  			// insert
  1310  			dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: Int64FloatVecJSON,
  1311  				start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true, WithRows: false}
  1312  			_, _ = insertData(ctx, t, mc, dp)
  1313  			mc.Flush(ctx, collName, false)
  1314  
  1315  			// create scann index
  1316  			indexScann, _ := entity.NewIndexSCANN(metricType, 16, withRawData)
  1317  			err := mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, indexScann, false)
  1318  			common.CheckErr(t, err, true)
  1319  
  1320  			// describe index
  1321  			indexes, _ := mc.DescribeIndex(ctx, collName, common.DefaultFloatVecFieldName)
  1322  			expIndex := entity.NewGenericIndex(common.DefaultFloatVecFieldName, entity.SCANN, indexScann.Params())
  1323  			common.CheckIndexResult(t, indexes, expIndex)
  1324  
  1325  			// load collection
  1326  			errLoad := mc.LoadCollection(ctx, collName, false)
  1327  			common.CheckErr(t, errLoad, true)
  1328  
  1329  			// search and output all fields
  1330  			sp, _ := entity.NewIndexSCANNSearchParam(8, 20)
  1331  			resSearch, errSearch := mc.Search(
  1332  				ctx, collName,
  1333  				[]string{},
  1334  				"",
  1335  				[]string{"*"},
  1336  				common.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeFloatVector),
  1337  				common.DefaultFloatVecFieldName,
  1338  				metricType,
  1339  				common.DefaultTopK,
  1340  				sp,
  1341  			)
  1342  			common.CheckErr(t, errSearch, true)
  1343  			common.CheckOutputFields(t, resSearch[0].Fields, []string{common.DefaultIntFieldName, common.DefaultFloatFieldName,
  1344  				common.DefaultJSONFieldName, common.DefaultFloatVecFieldName, common.DefaultDynamicFieldName})
  1345  			common.CheckSearchResult(t, resSearch, 1, common.DefaultTopK)
  1346  		}
  1347  	}
  1348  }
  1349  
  1350  // test range search with scann index
  1351  func TestRangeSearchScannL2(t *testing.T) {
  1352  	ctx := createContext(t, time.Second*common.DefaultTimeout)
  1353  	// connect
  1354  	mc := createMilvusClient(ctx, t)
  1355  
  1356  	// create collection
  1357  	cp := CollectionParams{CollectionFieldsType: Int64FloatVecJSON, AutoID: false, EnableDynamicField: true,
  1358  		ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
  1359  	collName := createCollection(ctx, t, mc, cp)
  1360  
  1361  	// insert
  1362  	dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: Int64FloatVecJSON,
  1363  		start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true, WithRows: false}
  1364  	_, _ = insertData(ctx, t, mc, dp)
  1365  
  1366  	// create scann index
  1367  	indexScann, _ := entity.NewIndexSCANN(entity.L2, 16, false)
  1368  	err := mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, indexScann, false)
  1369  	common.CheckErr(t, err, true)
  1370  
  1371  	// describe index
  1372  	indexes, _ := mc.DescribeIndex(ctx, collName, common.DefaultFloatVecFieldName)
  1373  	expIndex := entity.NewGenericIndex(common.DefaultFloatVecFieldName, entity.SCANN, indexScann.Params())
  1374  	common.CheckIndexResult(t, indexes, expIndex)
  1375  
  1376  	// load collection
  1377  	errLoad := mc.LoadCollection(ctx, collName, false)
  1378  	common.CheckErr(t, errLoad, true)
  1379  
  1380  	// search output all fields
  1381  	queryVec := common.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeFloatVector)
  1382  	sp, _ := entity.NewIndexSCANNSearchParam(8, 20)
  1383  	sp.AddRadius(20)
  1384  	sp.AddRangeFilter(15)
  1385  	resSearch, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultFloatVecFieldName,
  1386  		entity.L2, common.DefaultTopK, sp)
  1387  
  1388  	// verify error nil, output all fields, range score
  1389  	common.CheckErr(t, errSearch, true)
  1390  	common.CheckSearchResult(t, resSearch, 1, common.DefaultTopK)
  1391  	common.CheckOutputFields(t, resSearch[0].Fields, []string{common.DefaultIntFieldName, common.DefaultFloatFieldName,
  1392  		common.DefaultJSONFieldName, common.DefaultFloatVecFieldName, common.DefaultDynamicFieldName})
  1393  	for _, s := range resSearch[0].Scores {
  1394  		require.GreaterOrEqual(t, s, float32(15.0))
  1395  		require.Less(t, s, float32(20.0))
  1396  	}
  1397  
  1398  	// invalid range search: radius < range filter
  1399  	sp.AddRadius(15)
  1400  	sp.AddRangeFilter(20)
  1401  	_, errRange := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultFloatVecFieldName,
  1402  		entity.L2, common.DefaultTopK, sp)
  1403  	common.CheckErr(t, errRange, false, "must be less than radius")
  1404  }
  1405  
  1406  // test range search with scann index and IP COSINE metric type
  1407  func TestRangeSearchScannIPCosine(t *testing.T) {
  1408  	t.Skip("https://github.com/milvus-io/milvus/issues/32608")
  1409  	t.Parallel()
  1410  	for _, metricType := range []entity.MetricType{entity.IP, entity.COSINE} {
  1411  		ctx := createContext(t, time.Second*common.DefaultTimeout)
  1412  		// connect
  1413  		mc := createMilvusClient(ctx, t)
  1414  
  1415  		// create collection
  1416  		cp := CollectionParams{CollectionFieldsType: Int64FloatVecJSON, AutoID: false, EnableDynamicField: true,
  1417  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
  1418  		collName := createCollection(ctx, t, mc, cp)
  1419  
  1420  		// insert
  1421  		dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: Int64FloatVecJSON,
  1422  			start: 0, nb: common.DefaultNb * 4, dim: common.DefaultDim, EnableDynamicField: true, WithRows: false}
  1423  		_, _ = insertData(ctx, t, mc, dp)
  1424  		mc.Flush(ctx, collName, false)
  1425  
  1426  		// create scann index
  1427  		indexScann, _ := entity.NewIndexSCANN(metricType, 16, false)
  1428  		err := mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, indexScann, false)
  1429  		common.CheckErr(t, err, true)
  1430  
  1431  		// describe index
  1432  		indexes, _ := mc.DescribeIndex(ctx, collName, common.DefaultFloatVecFieldName)
  1433  		expIndex := entity.NewGenericIndex(common.DefaultFloatVecFieldName, entity.SCANN, indexScann.Params())
  1434  		common.CheckIndexResult(t, indexes, expIndex)
  1435  
  1436  		// load collection
  1437  		errLoad := mc.LoadCollection(ctx, collName, false)
  1438  		common.CheckErr(t, errLoad, true)
  1439  
  1440  		// range search filter distance and output all fields
  1441  		queryVec := common.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeFloatVector)
  1442  		sp, _ := entity.NewIndexSCANNSearchParam(8, 20)
  1443  
  1444  		// search without range
  1445  		resSearch, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultFloatVecFieldName,
  1446  			metricType, common.DefaultTopK, sp)
  1447  		common.CheckErr(t, errSearch, true)
  1448  		for _, s := range resSearch[0].Scores {
  1449  			log.Println(s)
  1450  		}
  1451  
  1452  		// range search
  1453  		var radius float64
  1454  		var rangeFilter float64
  1455  		if metricType == entity.COSINE {
  1456  			radius = 10
  1457  			rangeFilter = 50
  1458  		}
  1459  		if metricType == entity.IP {
  1460  			radius = 0.2
  1461  			rangeFilter = 0.8
  1462  		}
  1463  		sp.AddRadius(radius)
  1464  		sp.AddRangeFilter(rangeFilter)
  1465  		resRange, errRange := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultFloatVecFieldName,
  1466  			metricType, common.DefaultTopK, sp)
  1467  
  1468  		// verify error nil, output all fields, range score
  1469  		common.CheckErr(t, errRange, true)
  1470  		common.CheckSearchResult(t, resRange, 1, common.DefaultTopK)
  1471  		common.CheckOutputFields(t, resRange[0].Fields, []string{common.DefaultIntFieldName, common.DefaultFloatFieldName,
  1472  			common.DefaultJSONFieldName, common.DefaultFloatVecFieldName, common.DefaultDynamicFieldName})
  1473  		for _, s := range resSearch[0].Scores {
  1474  			log.Println(s)
  1475  			require.GreaterOrEqual(t, s, float32(radius))
  1476  			require.Less(t, s, float32(rangeFilter))
  1477  		}
  1478  
  1479  		// invalid range search: radius > range filter
  1480  		sp.AddRadius(20)
  1481  		sp.AddRangeFilter(10)
  1482  		_, errRange = mc.Search(ctx, collName, []string{}, "", []string{""}, queryVec, common.DefaultFloatVecFieldName,
  1483  			metricType, common.DefaultTopK, sp)
  1484  		common.CheckErr(t, errRange, false, "must be greater than radius")
  1485  	}
  1486  }
  1487  
  1488  // test range search with scann index and entity.HAMMING, entity.JACCARD metric type
  1489  func TestRangeSearchScannBinary(t *testing.T) {
  1490  	t.Parallel()
  1491  	for _, metricType := range common.SupportBinIvfFlatMetricType {
  1492  		ctx := createContext(t, time.Second*common.DefaultTimeout)
  1493  		// connect
  1494  		mc := createMilvusClient(ctx, t)
  1495  
  1496  		// create collection
  1497  		cp := CollectionParams{CollectionFieldsType: Int64BinaryVec, AutoID: false, EnableDynamicField: true,
  1498  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
  1499  		collName := createCollection(ctx, t, mc, cp)
  1500  
  1501  		// insert
  1502  		dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: Int64BinaryVec,
  1503  			start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true, WithRows: false}
  1504  		_, _ = insertData(ctx, t, mc, dp)
  1505  		mc.Flush(ctx, collName, false)
  1506  
  1507  		// create scann index
  1508  		indexBin, _ := entity.NewIndexBinIvfFlat(metricType, 16)
  1509  		err := mc.CreateIndex(ctx, collName, common.DefaultBinaryVecFieldName, indexBin, false)
  1510  		common.CheckErr(t, err, true)
  1511  
  1512  		// describe index
  1513  		indexes, _ := mc.DescribeIndex(ctx, collName, common.DefaultBinaryVecFieldName)
  1514  		expIndex := entity.NewGenericIndex(common.DefaultBinaryVecFieldName, entity.BinIvfFlat, indexBin.Params())
  1515  		common.CheckIndexResult(t, indexes, expIndex)
  1516  
  1517  		// load collection
  1518  		errLoad := mc.LoadCollection(ctx, collName, false)
  1519  		common.CheckErr(t, errLoad, true)
  1520  
  1521  		// range search filter distance and output all fields
  1522  		queryVec := common.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeBinaryVector)
  1523  		sp, _ := entity.NewIndexBinIvfFlatSearchParam(8)
  1524  		sp.AddRadius(100)
  1525  		sp.AddRangeFilter(0)
  1526  		resSearch, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultBinaryVecFieldName,
  1527  			metricType, common.DefaultTopK, sp)
  1528  
  1529  		// verify error nil, output all fields, range score
  1530  		common.CheckErr(t, errSearch, true)
  1531  		common.CheckSearchResult(t, resSearch, 1, common.DefaultTopK)
  1532  		common.CheckOutputFields(t, resSearch[0].Fields, []string{common.DefaultIntFieldName, common.DefaultFloatFieldName,
  1533  			common.DefaultBinaryVecFieldName, common.DefaultDynamicFieldName})
  1534  		for _, s := range resSearch[0].Scores {
  1535  			require.GreaterOrEqual(t, s, float32(0))
  1536  			require.Less(t, s, float32(100))
  1537  		}
  1538  
  1539  		// invalid range search: radius > range filter
  1540  		sp.AddRadius(0)
  1541  		sp.AddRangeFilter(100)
  1542  		_, errRange := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultBinaryVecFieldName,
  1543  			metricType, common.DefaultTopK, sp)
  1544  		common.CheckErr(t, errRange, false, "range_filter(100) must be less than radius(0)")
  1545  	}
  1546  }
  1547  
  1548  func TestVectorOutputField(t *testing.T) {
  1549  	ctx := createContext(t, time.Second*common.DefaultTimeout)
  1550  	// connect
  1551  	mc := createMilvusClient(ctx, t)
  1552  
  1553  	// create collection with data
  1554  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, false, true)
  1555  
  1556  	// load collection
  1557  	errLoad := mc.LoadCollection(ctx, collName, false)
  1558  	common.CheckErr(t, errLoad, true)
  1559  
  1560  	// search vector
  1561  	for i := 0; i < 20; i++ {
  1562  		sp, _ := entity.NewIndexHNSWSearchParam(74)
  1563  		searchResult, errSearch := mc.Search(
  1564  			ctx, collName,
  1565  			[]string{common.DefaultPartition},
  1566  			"",
  1567  			[]string{common.DefaultFloatVecFieldName},
  1568  			//[]entity.Vector{entity.FloatVector([]float32{0.1, 0.2})},
  1569  			common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector),
  1570  			common.DefaultFloatVecFieldName,
  1571  			entity.L2,
  1572  			common.DefaultTopK,
  1573  			sp,
  1574  		)
  1575  		common.CheckErr(t, errSearch, true)
  1576  		common.CheckOutputFields(t, searchResult[0].Fields, []string{common.DefaultFloatVecFieldName})
  1577  		common.CheckSearchResult(t, searchResult, common.DefaultNq, common.DefaultTopK)
  1578  		log.Printf("search %d done\n", i)
  1579  	}
  1580  }
  1581  
  1582  // test search with fp16/ bf16 /binary vector
  1583  func TestSearchMultiVectors(t *testing.T) {
  1584  	ctx := createContext(t, time.Second*common.DefaultTimeout*2)
  1585  	// connect
  1586  	mc := createMilvusClient(ctx, t)
  1587  
  1588  	// create -> insert [0, 3000) -> flush -> index -> load
  1589  	cp := CollectionParams{CollectionFieldsType: AllVectors, AutoID: false, EnableDynamicField: true,
  1590  		ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
  1591  
  1592  	dp := DataParams{DoInsert: true, CollectionFieldsType: AllVectors, start: 0, nb: common.DefaultNb * 2,
  1593  		dim: common.DefaultDim, EnableDynamicField: true}
  1594  
  1595  	// index params
  1596  	ips := make([]IndexParams, 4)
  1597  	var idx entity.Index
  1598  	for _, fieldName := range common.AllVectorsFieldsName {
  1599  		if fieldName == common.DefaultBinaryVecFieldName {
  1600  			idx, _ = entity.NewIndexBinFlat(entity.JACCARD, 64)
  1601  		} else {
  1602  			idx, _ = entity.NewIndexFlat(entity.L2)
  1603  		}
  1604  		ips = append(ips, IndexParams{BuildIndex: true, Index: idx, FieldName: fieldName, async: false})
  1605  	}
  1606  
  1607  	collName := prepareCollection(ctx, t, mc, cp, WithDataParams(dp), WithIndexParams(ips), WithCreateOption(client.WithConsistencyLevel(entity.ClStrong)))
  1608  
  1609  	// search with all kinds of vectors
  1610  	type mFieldNameType struct {
  1611  		fieldName  string
  1612  		fieldType  entity.FieldType
  1613  		metricType entity.MetricType
  1614  	}
  1615  	fnts := []mFieldNameType{
  1616  		{fieldName: common.DefaultFloatVecFieldName, fieldType: entity.FieldTypeFloatVector, metricType: entity.L2},
  1617  		{fieldName: common.DefaultBinaryVecFieldName, fieldType: entity.FieldTypeBinaryVector, metricType: entity.JACCARD},
  1618  		{fieldName: common.DefaultFloat16VecFieldName, fieldType: entity.FieldTypeFloat16Vector, metricType: entity.L2},
  1619  		{fieldName: common.DefaultBFloat16VecFieldName, fieldType: entity.FieldTypeBFloat16Vector, metricType: entity.L2},
  1620  	}
  1621  
  1622  	//sp, _ := entity.NewIndexHNSWSearchParam(20)
  1623  	sp, _ := entity.NewIndexFlatSearchParam()
  1624  	for _, fnt := range fnts {
  1625  		queryVec := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, fnt.fieldType)
  1626  
  1627  		// search
  1628  		resSearch, errSearch := mc.Search(ctx, collName, []string{}, fmt.Sprintf("%s > 10", common.DefaultIntFieldName),
  1629  			[]string{"*"}, queryVec, fnt.fieldName, fnt.metricType, common.DefaultTopK*2, sp)
  1630  		common.CheckErr(t, errSearch, true)
  1631  		common.CheckSearchResult(t, resSearch, common.DefaultNq, common.DefaultTopK*2)
  1632  		common.CheckOutputFields(t, resSearch[0].Fields, []string{common.DefaultIntFieldName, common.DefaultFloatVecFieldName,
  1633  			common.DefaultBinaryVecFieldName, common.DefaultFloat16VecFieldName, common.DefaultBFloat16VecFieldName, common.DefaultDynamicFieldName})
  1634  
  1635  		//pagination search
  1636  		resPage, errPage := mc.Search(ctx, collName, []string{}, fmt.Sprintf("%s > 10", common.DefaultIntFieldName),
  1637  			[]string{"*"}, queryVec, fnt.fieldName, fnt.metricType, common.DefaultTopK, sp, client.WithOffset(10))
  1638  		common.CheckErr(t, errPage, true)
  1639  		common.CheckSearchResult(t, resPage, common.DefaultNq, common.DefaultTopK)
  1640  		for i := 0; i < common.DefaultNq; i++ {
  1641  			require.Equal(t, resSearch[i].IDs.(*entity.ColumnInt64).Data()[10:], resPage[i].IDs.(*entity.ColumnInt64).Data())
  1642  		}
  1643  		common.CheckOutputFields(t, resPage[0].Fields, []string{common.DefaultIntFieldName, common.DefaultFloatVecFieldName,
  1644  			common.DefaultBinaryVecFieldName, common.DefaultFloat16VecFieldName, common.DefaultBFloat16VecFieldName, common.DefaultDynamicFieldName})
  1645  
  1646  		// range search
  1647  		sp.AddRadius(50.2)
  1648  		sp.AddRangeFilter(0)
  1649  		resRange, errRange := mc.Search(ctx, collName, []string{}, fmt.Sprintf("%s > 10", common.DefaultIntFieldName),
  1650  			[]string{"*"}, queryVec, fnt.fieldName, fnt.metricType, common.DefaultTopK, sp, client.WithOffset(10))
  1651  		common.CheckErr(t, errRange, true)
  1652  		common.CheckSearchResult(t, resRange, common.DefaultNq, common.DefaultTopK)
  1653  		common.CheckOutputFields(t, resRange[0].Fields, []string{common.DefaultIntFieldName, common.DefaultFloatVecFieldName,
  1654  			common.DefaultBinaryVecFieldName, common.DefaultFloat16VecFieldName, common.DefaultBFloat16VecFieldName, common.DefaultDynamicFieldName})
  1655  		for _, res := range resRange {
  1656  			for _, score := range res.Scores {
  1657  				require.GreaterOrEqual(t, score, float32(0))
  1658  				require.LessOrEqual(t, score, float32(50.2))
  1659  			}
  1660  		}
  1661  		// TODO iterator search
  1662  	}
  1663  }
  1664  
  1665  func TestSearchSparseVector(t *testing.T) {
  1666  	t.Parallel()
  1667  	idxInverted := entity.NewGenericIndex(common.DefaultSparseVecFieldName, "SPARSE_INVERTED_INDEX", map[string]string{"drop_ratio_build": "0.2", "metric_type": "IP"})
  1668  	idxWand := entity.NewGenericIndex(common.DefaultSparseVecFieldName, "SPARSE_WAND", map[string]string{"drop_ratio_build": "0.3", "metric_type": "IP"})
  1669  	for _, idx := range []entity.Index{idxInverted, idxWand} {
  1670  		ctx := createContext(t, time.Second*common.DefaultTimeout*2)
  1671  		// connect
  1672  		mc := createMilvusClient(ctx, t)
  1673  
  1674  		// create -> insert [0, 3000) -> flush -> index -> load
  1675  		cp := CollectionParams{CollectionFieldsType: Int64VarcharSparseVec, AutoID: false, EnableDynamicField: true,
  1676  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim, MaxLength: common.TestMaxLen}
  1677  
  1678  		dp := DataParams{DoInsert: true, CollectionFieldsType: Int64VarcharSparseVec, start: 0, nb: common.DefaultNb * 4,
  1679  			dim: common.DefaultDim, EnableDynamicField: true}
  1680  
  1681  		// index params
  1682  		idxHnsw, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
  1683  		ips := []IndexParams{
  1684  			{BuildIndex: true, Index: idx, FieldName: common.DefaultSparseVecFieldName, async: false},
  1685  			{BuildIndex: true, Index: idxHnsw, FieldName: common.DefaultFloatVecFieldName, async: false},
  1686  		}
  1687  		collName := prepareCollection(ctx, t, mc, cp, WithDataParams(dp), WithIndexParams(ips), WithCreateOption(client.WithConsistencyLevel(entity.ClStrong)))
  1688  
  1689  		// search
  1690  		queryVec := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeSparseVector)
  1691  		sp, _ := entity.NewIndexSparseInvertedSearchParam(0.2)
  1692  		resSearch, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultSparseVecFieldName,
  1693  			entity.IP, common.DefaultTopK, sp)
  1694  		common.CheckErr(t, errSearch, true)
  1695  		require.Len(t, resSearch, common.DefaultNq)
  1696  		outputFields := []string{common.DefaultIntFieldName, common.DefaultVarcharFieldName, common.DefaultFloatVecFieldName,
  1697  			common.DefaultSparseVecFieldName, common.DefaultDynamicFieldName}
  1698  		for _, res := range resSearch {
  1699  			require.LessOrEqual(t, res.ResultCount, common.DefaultTopK)
  1700  			if res.ResultCount == common.DefaultTopK {
  1701  				common.CheckOutputFields(t, resSearch[0].Fields, outputFields)
  1702  			}
  1703  		}
  1704  	}
  1705  }
  1706  
  1707  // test search with invalid sparse vector
  1708  func TestSearchInvalidSparseVector(t *testing.T) {
  1709  	t.Skip("https://github.com/milvus-io/milvus/issues/32368")
  1710  	t.Parallel()
  1711  	idxInverted := entity.NewGenericIndex(common.DefaultSparseVecFieldName, "SPARSE_INVERTED_INDEX", map[string]string{"drop_ratio_build": "0.2", "metric_type": "IP"})
  1712  	idxWand := entity.NewGenericIndex(common.DefaultSparseVecFieldName, "SPARSE_WAND", map[string]string{"drop_ratio_build": "0.3", "metric_type": "IP"})
  1713  	for _, idx := range []entity.Index{idxInverted, idxWand} {
  1714  		ctx := createContext(t, time.Second*common.DefaultTimeout*2)
  1715  		// connect
  1716  		mc := createMilvusClient(ctx, t)
  1717  
  1718  		// create -> insert [0, 3000) -> flush -> index -> load
  1719  		cp := CollectionParams{CollectionFieldsType: Int64VarcharSparseVec, AutoID: false, EnableDynamicField: true,
  1720  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim, MaxLength: common.TestMaxLen}
  1721  
  1722  		dp := DataParams{DoInsert: true, CollectionFieldsType: Int64VarcharSparseVec, start: 0, nb: common.DefaultNb,
  1723  			dim: common.DefaultDim, EnableDynamicField: true}
  1724  
  1725  		// index params
  1726  		idxHnsw, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
  1727  		ips := []IndexParams{
  1728  			{BuildIndex: true, Index: idx, FieldName: common.DefaultSparseVecFieldName, async: false},
  1729  			{BuildIndex: true, Index: idxHnsw, FieldName: common.DefaultFloatVecFieldName, async: false},
  1730  		}
  1731  		collName := prepareCollection(ctx, t, mc, cp, WithDataParams(dp), WithIndexParams(ips), WithCreateOption(client.WithConsistencyLevel(entity.ClStrong)))
  1732  		sp, _ := entity.NewIndexSparseInvertedSearchParam(0)
  1733  
  1734  		_, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, []entity.Vector{}, common.DefaultSparseVecFieldName,
  1735  			entity.IP, common.DefaultTopK, sp)
  1736  		common.CheckErr(t, errSearch, false, "nq (number of search vector per search request) should be in range [1, 16384]")
  1737  
  1738  		vector1, err := entity.NewSliceSparseEmbedding([]uint32{}, []float32{})
  1739  		common.CheckErr(t, err, true)
  1740  		searchRes, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, []entity.Vector{vector1}, common.DefaultSparseVecFieldName,
  1741  			entity.IP, common.DefaultTopK, sp)
  1742  		common.CheckErr(t, errSearch, true)
  1743  		common.CheckSearchResult(t, searchRes, 1, 0)
  1744  
  1745  		positions := make([]uint32, 100)
  1746  		values := make([]float32, 100)
  1747  		for i := 0; i < 100; i++ {
  1748  			positions[i] = uint32(1)
  1749  			values[i] = rand.Float32()
  1750  		}
  1751  		vector, _ := entity.NewSliceSparseEmbedding(positions, values)
  1752  		_, errSearch1 := mc.Search(ctx, collName, []string{}, "", []string{"*"}, []entity.Vector{vector}, common.DefaultSparseVecFieldName,
  1753  			entity.IP, common.DefaultTopK, sp)
  1754  		common.CheckErr(t, errSearch1, false, "unsorted or same indices in sparse float vector")
  1755  	}
  1756  }
  1757  
  1758  func TestSearchEmptySparseCollection(t *testing.T) {
  1759  	t.Parallel()
  1760  	idxInverted := entity.NewGenericIndex(common.DefaultSparseVecFieldName, "SPARSE_INVERTED_INDEX", map[string]string{"drop_ratio_build": "0.2", "metric_type": "IP"})
  1761  	for _, idx := range []entity.Index{idxInverted} {
  1762  		ctx := createContext(t, time.Second*common.DefaultTimeout*2)
  1763  		// connect
  1764  		mc := createMilvusClient(ctx, t)
  1765  
  1766  		// create -> insert [0, 3000) -> flush -> index -> load
  1767  		cp := CollectionParams{CollectionFieldsType: Int64VarcharSparseVec, AutoID: false, EnableDynamicField: true,
  1768  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim, MaxLength: common.TestMaxLen}
  1769  
  1770  		dp := DataParams{DoInsert: false}
  1771  
  1772  		// index params
  1773  		idxHnsw, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
  1774  		ips := []IndexParams{
  1775  			{BuildIndex: true, Index: idx, FieldName: common.DefaultSparseVecFieldName, async: false},
  1776  			{BuildIndex: true, Index: idxHnsw, FieldName: common.DefaultFloatVecFieldName, async: false},
  1777  		}
  1778  		collName := prepareCollection(ctx, t, mc, cp, WithDataParams(dp), WithIndexParams(ips), WithCreateOption(client.WithConsistencyLevel(entity.ClStrong)))
  1779  
  1780  		// search
  1781  		sp, _ := entity.NewIndexSparseInvertedSearchParam(0)
  1782  		queryVec := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeSparseVector)
  1783  		resSearch, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultSparseVecFieldName,
  1784  			entity.IP, common.DefaultTopK, sp)
  1785  		common.CheckErr(t, errSearch, true)
  1786  		common.CheckSearchResult(t, resSearch, common.DefaultNq, 0)
  1787  	}
  1788  }
  1789  
  1790  func TestSearchSparseVectorPagination(t *testing.T) {
  1791  	t.Parallel()
  1792  	idxInverted, _ := entity.NewIndexSparseInverted(entity.IP, 0.2)
  1793  	idxWand, _ := entity.NewIndexSparseWAND(entity.IP, 0.2)
  1794  	for _, idx := range []entity.Index{idxInverted, idxWand} {
  1795  		ctx := createContext(t, time.Second*common.DefaultTimeout*2)
  1796  		// connect
  1797  		mc := createMilvusClient(ctx, t)
  1798  
  1799  		// create -> insert [0, 3000) -> flush -> index -> load
  1800  		cp := CollectionParams{CollectionFieldsType: Int64VarcharSparseVec, AutoID: false, EnableDynamicField: true,
  1801  			ShardsNum: common.DefaultShards, Dim: common.DefaultDim, MaxLength: common.TestMaxLen}
  1802  
  1803  		dp := DataParams{DoInsert: true, CollectionFieldsType: Int64VarcharSparseVec, start: 0, nb: common.DefaultNb * 4,
  1804  			dim: common.DefaultDim, EnableDynamicField: true}
  1805  
  1806  		// index params
  1807  		idxHnsw, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
  1808  		ips := []IndexParams{
  1809  			{BuildIndex: true, Index: idx, FieldName: common.DefaultSparseVecFieldName, async: false},
  1810  			{BuildIndex: true, Index: idxHnsw, FieldName: common.DefaultFloatVecFieldName, async: false},
  1811  		}
  1812  		collName := prepareCollection(ctx, t, mc, cp, WithDataParams(dp), WithIndexParams(ips), WithCreateOption(client.WithConsistencyLevel(entity.ClStrong)))
  1813  
  1814  		// search
  1815  		queryVec := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeSparseVector)
  1816  		sp, _ := entity.NewIndexSparseInvertedSearchParam(0.2)
  1817  		resSearch, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultSparseVecFieldName,
  1818  			entity.IP, common.DefaultTopK, sp)
  1819  		common.CheckErr(t, errSearch, true)
  1820  		require.Len(t, resSearch, common.DefaultNq)
  1821  
  1822  		pageSearch, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultSparseVecFieldName,
  1823  			entity.IP, 5, sp, client.WithOffset(5))
  1824  		common.CheckErr(t, errSearch, true)
  1825  		require.Len(t, pageSearch, common.DefaultNq)
  1826  		for i := 0; i < len(resSearch); i++ {
  1827  			if resSearch[i].ResultCount == common.DefaultTopK && pageSearch[i].ResultCount == 5 {
  1828  				require.Equal(t, resSearch[i].IDs.(*entity.ColumnInt64).Data()[5:], pageSearch[i].IDs.(*entity.ColumnInt64).Data())
  1829  			}
  1830  		}
  1831  	}
  1832  }
  1833  
  1834  // test sparse vector unsupported search: TODO iterator search
  1835  func TestSearchSparseVectorNotSupported(t *testing.T) {
  1836  	t.Skip("Go-sdk support iterator search in progress")
  1837  }
  1838  
  1839  func TestRangeSearchSparseVector(t *testing.T) {
  1840  	ctx := createContext(t, time.Second*common.DefaultTimeout*2)
  1841  	// connect
  1842  	mc := createMilvusClient(ctx, t)
  1843  
  1844  	// create -> insert [0, 3000) -> flush -> index -> load
  1845  	cp := CollectionParams{CollectionFieldsType: Int64VarcharSparseVec, AutoID: false, EnableDynamicField: true,
  1846  		ShardsNum: common.DefaultShards, Dim: common.DefaultDim, MaxLength: common.TestMaxLen}
  1847  
  1848  	dp := DataParams{DoInsert: true, CollectionFieldsType: Int64VarcharSparseVec, start: 0, nb: common.DefaultNb * 4,
  1849  		dim: common.DefaultDim, EnableDynamicField: true}
  1850  
  1851  	// index params
  1852  	idxHnsw, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
  1853  	idxWand := entity.NewGenericIndex(common.DefaultSparseVecFieldName, "SPARSE_WAND", map[string]string{"drop_ratio_build": "0.1", "metric_type": "IP"})
  1854  	ips := []IndexParams{
  1855  		{BuildIndex: true, Index: idxWand, FieldName: common.DefaultSparseVecFieldName, async: false},
  1856  		{BuildIndex: true, Index: idxHnsw, FieldName: common.DefaultFloatVecFieldName, async: false},
  1857  	}
  1858  	collName := prepareCollection(ctx, t, mc, cp, WithDataParams(dp), WithIndexParams(ips), WithCreateOption(client.WithConsistencyLevel(entity.ClStrong)))
  1859  
  1860  	// range search
  1861  	queryVec := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeSparseVector)
  1862  	sp, _ := entity.NewIndexSparseInvertedSearchParam(0.3)
  1863  
  1864  	// without range
  1865  	resRange, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultSparseVecFieldName,
  1866  		entity.IP, common.DefaultTopK, sp)
  1867  	common.CheckErr(t, errSearch, true)
  1868  	require.Len(t, resRange, common.DefaultNq)
  1869  	for _, res := range resRange {
  1870  		log.Println(res.Scores)
  1871  	}
  1872  
  1873  	sp.AddRadius(0)
  1874  	sp.AddRangeFilter(0.8)
  1875  	resRange, errSearch = mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVec, common.DefaultSparseVecFieldName,
  1876  		entity.IP, common.DefaultTopK, sp)
  1877  	common.CheckErr(t, errSearch, true)
  1878  	require.Len(t, resRange, common.DefaultNq)
  1879  	for _, res := range resRange {
  1880  		for _, s := range res.Scores {
  1881  			require.GreaterOrEqual(t, s, float32(0))
  1882  			require.Less(t, s, float32(0.8))
  1883  		}
  1884  	}
  1885  }
  1886  
  1887  // TODO offset and limit
  1888  // TODO consistency level
  1889  // TODO WithGuaranteeTimestamp
  1890  // TODO ignore growing