Skip to content

Commit

Permalink
test: update cases for search params support and groupby issue fix (#…
Browse files Browse the repository at this point in the history
…38852)

issue: #38343 #33419
- update cases for WithSearchParam
- remove skip for groupby search issue
- update output query dynamic case for server changes

Signed-off-by: ThreadDao <[email protected]>
  • Loading branch information
ThreadDao authored Dec 31, 2024
1 parent 2f6d4ef commit ba0c7b8
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 41 deletions.
14 changes: 5 additions & 9 deletions tests/go_client/testcases/groupby_search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ func prepareDataForGroupBySearch(t *testing.T, loopInsert int, insertNi int, idx
// -> verify every top passage is the top of whole group
// output_fields: pk + groupBy
func TestSearchGroupByFloatDefault(t *testing.T) {
t.Skip("https://github.com/milvus-io/milvus/issues/38343")
t.Parallel()
for _, idx := range genGroupByVectorIndex(entity.L2) {
// prepare data
Expand Down Expand Up @@ -150,7 +149,6 @@ func TestSearchGroupByFloatDefault(t *testing.T) {
}

func TestSearchGroupByFloatDefaultCosine(t *testing.T) {
t.Skip("https://github.com/milvus-io/milvus/issues/38343")
t.Parallel()
for _, idx := range genGroupByVectorIndex(entity.COSINE) {
// prepare data
Expand Down Expand Up @@ -299,7 +297,6 @@ func TestSearchGroupByBinaryDefault(t *testing.T) {
// default Bounded ConsistencyLevel -> succ ??
// strong ConsistencyLevel -> error
func TestSearchGroupByBinaryGrowing(t *testing.T) {
t.Skip("https://github.com/milvus-io/milvus/issues/38343")
t.Parallel()
for _, metricType := range hp.SupportBinIvfFlatMetricType {
idxBinIvfFlat := index.NewBinIvfFlatIndex(metricType, 128)
Expand Down Expand Up @@ -331,6 +328,7 @@ func TestSearchGroupByBinaryGrowing(t *testing.T) {

// groupBy in growing segments, maybe growing index or brute force
func TestSearchGroupByFloatGrowing(t *testing.T) {
t.Parallel()
for _, metricType := range hp.SupportFloatMetricType {
idxHnsw := index.NewHNSWIndex(metricType, 8, 96)
mc, ctx, collName := prepareDataForGroupBySearch(t, 100, 200, idxHnsw, true)
Expand Down Expand Up @@ -384,6 +382,7 @@ func TestSearchGroupByFloatGrowing(t *testing.T) {

// groupBy + pagination
func TestSearchGroupByPagination(t *testing.T) {
t.Parallel()
// create index and load
idx := index.NewHNSWIndex(entity.COSINE, 8, 96)
mc, ctx, collName := prepareDataForGroupBySearch(t, 10, 1000, idx, false)
Expand Down Expand Up @@ -444,19 +443,16 @@ func TestSearchGroupByIterator(t *testing.T) {

// groupBy + range search -> not supported
func TestSearchGroupByRangeSearch(t *testing.T) {
t.Skipf("Waiting for support for specifying search parameters")
t.Skipf("https://github.com/milvus-io/milvus/issues/38846")
idxHnsw := index.NewHNSWIndex(entity.COSINE, 8, 96)
mc, ctx, collName := prepareDataForGroupBySearch(t, 1, 1000, idxHnsw, true)

// groupBy search with range
queryVec := hp.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector)

// sp, _ := index.NewHNSWIndexSearchParam(50)
// sp.AddRadius(0)
// sp.AddRangeFilter(0.8)

// range search
_, err := mc.Search(ctx, client.NewSearchOption(collName, common.DefaultLimit, queryVec).WithGroupByField(common.DefaultVarcharFieldName).WithANNSField(common.DefaultFloatVecFieldName))
_, err := mc.Search(ctx, client.NewSearchOption(collName, common.DefaultLimit, queryVec).WithGroupByField(common.DefaultVarcharFieldName).
WithANNSField(common.DefaultFloatVecFieldName).WithSearchParam("radius", "0").WithSearchParam("range_filter", "0.8"))
common.CheckErr(t, err, false, "Not allowed to do range-search when doing search-group-by")
}

Expand Down
8 changes: 4 additions & 4 deletions tests/go_client/testcases/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ func TestQueryWithoutExpr(t *testing.T) {
// test query with part not existed field ["aa", "$meat"]: error or as dynamic field
// test query with repeated field: ["*", "$meat"], ["floatVec", floatVec"] unique field
func TestQueryOutputFields(t *testing.T) {
t.Skip("verify TODO")
t.Parallel()
ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout)
mc := createDefaultMilvusClient(ctx, t)
Expand Down Expand Up @@ -193,16 +192,17 @@ func TestQueryOutputFields(t *testing.T) {
common.CheckErr(t, err1, false, "not exist")
}

// query with not existed field -> output field as dynamic or error
// query with not existed field -> output empty data field as dynamic or error
fakeName := "aaa"
res2, err2 := mc.Query(ctx, client.NewQueryOption(schema.CollectionName).WithConsistencyLevel(entity.ClStrong).WithFilter(expr).WithOutputFields(fakeName))
if enableDynamic {
common.CheckErr(t, err2, true)
for _, c := range res2.Fields {
log.Debug("data", zap.String("name", c.Name()), zap.Any("type", c.Type()), zap.Any("data", c.FieldData()))
log.Info("data", zap.String("name", c.Name()), zap.Any("type", c.Type()), zap.Any("data", c.FieldData()))
}
common.CheckOutputFields(t, []string{common.DefaultInt64FieldName, fakeName}, res2.Fields)
dynamicColumn := hp.MergeColumnsToDynamic(10, hp.GenDynamicColumnData(0, 10), common.DefaultDynamicFieldName)
dynamicColumn := hp.MergeColumnsToDynamic(10, []column.Column{}, common.DefaultDynamicFieldName)
// dynamicColumn := hp.MergeColumnsToDynamic(10, hp.GenDynamicColumnData(0, 10), common.DefaultDynamicFieldName)
expColumns := []column.Column{
hp.GenColumnData(10, entity.FieldTypeInt64, *hp.TNewDataOption()),
column.NewColumnDynamic(dynamicColumn, fakeName),
Expand Down
99 changes: 71 additions & 28 deletions tests/go_client/testcases/search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package testcases
import (
"fmt"
"math/rand"
"strconv"
"testing"
"time"

Expand Down Expand Up @@ -453,7 +454,6 @@ func TestSearchEmptyInvalidVectors(t *testing.T) {

// test search metric type isn't the same with index metric type
func TestSearchNotMatchMetricType(t *testing.T) {
t.Skip("Waiting for support for specifying search parameters")
ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout)
mc := createDefaultMilvusClient(ctx, t)

Expand All @@ -465,7 +465,7 @@ func TestSearchNotMatchMetricType(t *testing.T) {
prepare.Load(ctx, t, mc, hp.NewLoadParams(schema.CollectionName))

vectors := hp.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeFloatVector)
_, errSearchEmpty := mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors))
_, errSearchEmpty := mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).WithSearchParam("metric_type", "L2"))
common.CheckErr(t, errSearchEmpty, false, "metric type not match: invalid parameter")
}

Expand Down Expand Up @@ -507,12 +507,6 @@ func TestSearchInvalidOffset(t *testing.T) {

// test search with invalid search params
func TestSearchInvalidSearchParams(t *testing.T) {
t.Skip("Waiting for support for specifying search parameters")
}

// search with index hnsw search param ef < topK -> error
func TestSearchEfHnsw(t *testing.T) {
t.Skip("Waiting for support for specifying search parameters")
ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout)
mc := createDefaultMilvusClient(ctx, t)

Expand All @@ -524,18 +518,29 @@ func TestSearchEfHnsw(t *testing.T) {
prepare.Load(ctx, t, mc, hp.NewLoadParams(schema.CollectionName))

vectors := hp.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeFloatVector)
_, err := mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors))
common.CheckErr(t, err, false, "ef(7) should be larger than k(10)")
}

// test search params mismatch index type, hnsw index and ivf sq8 search param -> search with default hnsw params, ef=topK
func TestSearchSearchParamsMismatchIndex(t *testing.T) {
t.Skip("Waiting for support for specifying search parameters")
// search with invalid hnsw ef
invalidEfs := []int{-1, 0, 32769}
for _, invalidEf := range invalidEfs {
_, errHnsw := mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).WithSearchParam("ef", strconv.Itoa(invalidEf)))
common.CheckErr(t, errHnsw, true, "No error for invalid search params")
}

// test search params mismatch index type, hnsw index and ivf sq8 search param -> search with default hnsw params, ef=topK
invalidNprobes := []int{-1, 0, 65537}
for _, invalidNprobe := range invalidNprobes {
_, errHnsw := mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).WithSearchParam("nprobe", strconv.Itoa(invalidNprobe)))
common.CheckErr(t, errHnsw, true, "No error for invalid search params")
}

// search with index hnsw search param ef < topK -> error
res, err := mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).WithSearchParam("ef", "7"))
common.CheckErr(t, err, true, "ef(7) should be larger than k(10), but no error")
common.CheckSearchResult(t, res, 1, common.DefaultLimit)
}

// search with index scann search param ef < topK -> error
func TestSearchInvalidScannReorderK(t *testing.T) {
t.Skip("Waiting for support for specifying search parameters")
ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout)
mc := createDefaultMilvusClient(ctx, t)

Expand All @@ -548,36 +553,49 @@ func TestSearchInvalidScannReorderK(t *testing.T) {
prepare.Load(ctx, t, mc, hp.NewLoadParams(schema.CollectionName))

// search with invalid reorder_k < topK
vectors := hp.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeFloatVector)

// search with invalid hnsw ef
_, errScann := mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).
WithSearchParam("nprobe", "8").WithSearchParam("reorder_k", strconv.Itoa(common.DefaultLimit-1)))
common.CheckErr(t, errScann, true, "No error for invalid search params")

// valid scann index search reorder_k
res, err := mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).
WithSearchParam("nprobe", "8").WithSearchParam("reorder_k", "20"))
common.CheckErr(t, err, true)
common.CheckSearchResult(t, res, 1, common.DefaultLimit)
}

// test search with scann index params: with_raw_data and metrics_type [L2, IP, COSINE]
func TestSearchScannAllMetricsWithRawData(t *testing.T) {
t.Skip("Waiting for support scann index params withRawData")
t.Parallel()
/*for _, withRawData := range []bool{true, false} {
for _, withRawData := range []bool{true, false} {
for _, metricType := range []entity.MetricType{entity.L2, entity.IP, entity.COSINE} {
ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout)
mc := createDefaultMilvusClient(ctx, t)

prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64VecJSON), hp.TNewFieldsOption(), hp.TNewSchemaOption())
prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema, 500), hp.TNewDataOption())
prepare, schema := hp.CollPrepare.CreateCollection(ctx, t, mc, hp.NewCreateCollectionParams(hp.Int64VecJSON),
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).TWithFieldIndex(map[string]index.Index{
common.DefaultFloatVecFieldName: index.NewSCANNIndex(entity.COSINE, 16),
common.DefaultFloatVecFieldName: index.NewSCANNIndex(metricType, 16, withRawData),
}))
prepare.Load(ctx, t, mc, hp.NewLoadParams(schema.CollectionName))

// search and output all fields
vectors := hp.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeFloatVector)
resSearch, errSearch := mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).WithConsistencyLevel(entity.ClStrong).WithOutputFields([]string{"*"}))
vectors := hp.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector)
resSearch, errSearch := mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, vectors).
WithConsistencyLevel(entity.ClStrong).WithOutputFields("*"))
common.CheckErr(t, errSearch, true)
common.CheckOutputFields(t, []string{common.DefaultInt64FieldName, common.DefaultFloatFieldName,
common.DefaultJSONFieldName, common.DefaultFloatVecFieldName, common.DefaultDynamicFieldName}, resSearch[0].Fields)
common.CheckSearchResult(t, resSearch, 1, common.DefaultLimit)
common.CheckOutputFields(t, []string{
common.DefaultInt64FieldName, common.DefaultJSONFieldName,
common.DefaultFloatVecFieldName, common.DefaultDynamicFieldName,
}, resSearch[0].Fields)
common.CheckSearchResult(t, resSearch, common.DefaultNq, common.DefaultLimit)
}
}*/
}
}

// test search with valid expression
Expand Down Expand Up @@ -1061,7 +1079,7 @@ func TestSearchSparseVectorNotSupported(t *testing.T) {
}

func TestRangeSearchSparseVector(t *testing.T) {
t.Skip("Waiting for support range search")
t.Skipf("https://github.com/milvus-io/milvus/issues/38846")
ctx := hp.CreateContext(t, time.Second*common.DefaultTimeout*2)
mc := createDefaultMilvusClient(ctx, t)

Expand All @@ -1072,5 +1090,30 @@ func TestRangeSearchSparseVector(t *testing.T) {
prepare.InsertData(ctx, t, mc, hp.NewInsertParams(schema), hp.TNewDataOption().TWithSparseMaxLen(128))
prepare.FlushData(ctx, t, mc, schema.CollectionName)

// TODO range search
// range search
queryVec := hp.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeSparseVector)

resRange, errSearch := mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, queryVec).WithSearchParam("drop_ratio_search", "0.2"))
common.CheckErr(t, errSearch, true)
require.Len(t, resRange, common.DefaultNq)
for _, res := range resRange {
log.Info("default search", zap.Any("score", res.Scores))
}

radius := 10
rangeFilter := 30
resRange, errSearch = mc.Search(ctx, client.NewSearchOption(schema.CollectionName, common.DefaultLimit, queryVec).
WithSearchParam("drop_ratio_search", "0.2").WithSearchParam("radius", strconv.Itoa(radius)).WithSearchParam("range_filter", strconv.Itoa(rangeFilter)))
common.CheckErr(t, errSearch, true)
common.CheckErr(t, errSearch, true)
require.Len(t, resRange, common.DefaultNq)
for _, res := range resRange {
log.Info("range search", zap.Any("score", res.Scores))
}
for _, res := range resRange {
for _, s := range res.Scores {
require.GreaterOrEqual(t, s, float32(10))
require.Less(t, s, float32(30))
}
}
}

0 comments on commit ba0c7b8

Please sign in to comment.