mirror of
https://gitee.com/milvus-io/milvus.git
synced 2024-11-29 18:38:44 +08:00
fix: [restful v2] align search api with milvus client (#30946)
issue: #30688 fix: [restful v2] align search api with milvus client #30688 fix: [restful v2] DescribeIndex return Response{ Status: IndexNotFound }, nil #30722 Signed-off-by: PowderLi <min.li@zilliz.com>
This commit is contained in:
parent
21b41e96fc
commit
4869aaeb94
@ -911,7 +911,7 @@ func (h *HandlersV1) search(c *gin.Context) {
|
||||
DbName: httpReq.DbName,
|
||||
CollectionName: httpReq.CollectionName,
|
||||
Dsl: httpReq.Filter,
|
||||
PlaceholderGroup: vector2PlaceholderGroupBytes(httpReq.Vector),
|
||||
PlaceholderGroup: vectors2PlaceholderGroupBytes([][]float32{httpReq.Vector}),
|
||||
DslType: commonpb.DslType_BoolExprV1,
|
||||
OutputFields: httpReq.OutputFields,
|
||||
SearchParams: searchParams,
|
||||
|
@ -750,7 +750,6 @@ func generateSearchParams(ctx context.Context, c *gin.Context, reqParams map[str
|
||||
bs, _ := json.Marshal(params)
|
||||
searchParams := []*commonpb.KeyValuePair{
|
||||
{Key: Params, Value: string(bs)},
|
||||
{Key: ParamRoundDecimal, Value: "-1"},
|
||||
}
|
||||
return searchParams, nil
|
||||
}
|
||||
@ -764,11 +763,12 @@ func (h *HandlersV2) search(ctx context.Context, c *gin.Context, anyReq any, dbN
|
||||
searchParams = append(searchParams, &commonpb.KeyValuePair{Key: common.TopKKey, Value: strconv.FormatInt(int64(httpReq.Limit), 10)})
|
||||
searchParams = append(searchParams, &commonpb.KeyValuePair{Key: ParamOffset, Value: strconv.FormatInt(int64(httpReq.Offset), 10)})
|
||||
searchParams = append(searchParams, &commonpb.KeyValuePair{Key: ParamGroupByField, Value: httpReq.GroupByField})
|
||||
searchParams = append(searchParams, &commonpb.KeyValuePair{Key: ParamRoundDecimal, Value: "-1"})
|
||||
req := &milvuspb.SearchRequest{
|
||||
DbName: dbName,
|
||||
CollectionName: httpReq.CollectionName,
|
||||
Dsl: httpReq.Filter,
|
||||
PlaceholderGroup: vector2PlaceholderGroupBytes(httpReq.Vector),
|
||||
PlaceholderGroup: vectors2PlaceholderGroupBytes(httpReq.Vector),
|
||||
DslType: commonpb.DslType_BoolExprV1,
|
||||
OutputFields: httpReq.OutputFields,
|
||||
PartitionNames: httpReq.PartitionNames,
|
||||
@ -816,11 +816,12 @@ func (h *HandlersV2) hybridSearch(ctx context.Context, c *gin.Context, anyReq an
|
||||
searchParams = append(searchParams, &commonpb.KeyValuePair{Key: ParamOffset, Value: strconv.FormatInt(int64(subReq.Offset), 10)})
|
||||
searchParams = append(searchParams, &commonpb.KeyValuePair{Key: ParamGroupByField, Value: subReq.GroupByField})
|
||||
searchParams = append(searchParams, &commonpb.KeyValuePair{Key: proxy.AnnsFieldKey, Value: subReq.AnnsField})
|
||||
searchParams = append(searchParams, &commonpb.KeyValuePair{Key: ParamRoundDecimal, Value: "-1"})
|
||||
searchReq := &milvuspb.SearchRequest{
|
||||
DbName: dbName,
|
||||
CollectionName: httpReq.CollectionName,
|
||||
Dsl: subReq.Filter,
|
||||
PlaceholderGroup: vector2PlaceholderGroupBytes(subReq.Vector),
|
||||
PlaceholderGroup: vectors2PlaceholderGroupBytes(subReq.Vector),
|
||||
DslType: commonpb.DslType_BoolExprV1,
|
||||
OutputFields: httpReq.OutputFields,
|
||||
PartitionNames: httpReq.PartitionNames,
|
||||
@ -835,7 +836,7 @@ func (h *HandlersV2) hybridSearch(ctx context.Context, c *gin.Context, anyReq an
|
||||
{Key: proxy.RankTypeKey, Value: httpReq.Rerank.Strategy},
|
||||
{Key: proxy.RankParamsKey, Value: string(bs)},
|
||||
{Key: ParamLimit, Value: strconv.FormatInt(int64(httpReq.Limit), 10)},
|
||||
{Key: "round_decimal", Value: strconv.FormatInt(int64(-1), 10)},
|
||||
{Key: ParamRoundDecimal, Value: "-1"},
|
||||
}
|
||||
resp, err := wrapperProxy(ctx, c, req, h.checkAuth, false, func(reqCtx context.Context, req any) (interface{}, error) {
|
||||
return h.proxy.HybridSearch(reqCtx, req.(*milvuspb.HybridSearchRequest))
|
||||
@ -1351,6 +1352,11 @@ func (h *HandlersV2) listIndexes(ctx context.Context, c *gin.Context, anyReq any
|
||||
IndexDescriptions: []*milvuspb.IndexDescription{},
|
||||
}, nil
|
||||
}
|
||||
if resp != nil && errors.Is(merr.Error(resp.Status), merr.ErrIndexNotFound) {
|
||||
return &milvuspb.DescribeIndexResponse{
|
||||
IndexDescriptions: []*milvuspb.IndexDescription{},
|
||||
}, nil
|
||||
}
|
||||
return resp, err
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -604,6 +604,9 @@ func TestMethodGet(t *testing.T) {
|
||||
mp.EXPECT().GetLoadState(mock.Anything, mock.Anything).Return(&DefaultLoadStateResp, nil).Twice()
|
||||
mp.EXPECT().DescribeIndex(mock.Anything, mock.Anything).Return(&DefaultDescIndexesReqp, nil).Times(3)
|
||||
mp.EXPECT().DescribeIndex(mock.Anything, mock.Anything).Return(nil, merr.WrapErrIndexNotFoundForCollection(DefaultCollectionName)).Once()
|
||||
mp.EXPECT().DescribeIndex(mock.Anything, mock.Anything).Return(&milvuspb.DescribeIndexResponse{
|
||||
Status: merr.Status(merr.WrapErrIndexNotFoundForCollection(DefaultCollectionName)),
|
||||
}, nil).Once()
|
||||
mp.EXPECT().GetCollectionStatistics(mock.Anything, mock.Anything).Return(&milvuspb.GetCollectionStatisticsResponse{
|
||||
Status: commonSuccessStatus,
|
||||
Stats: []*commonpb.KeyValuePair{
|
||||
@ -779,6 +782,9 @@ func TestMethodGet(t *testing.T) {
|
||||
queryTestCases = append(queryTestCases, rawTestCase{
|
||||
path: versionalV2(IndexCategory, ListAction),
|
||||
})
|
||||
queryTestCases = append(queryTestCases, rawTestCase{
|
||||
path: versionalV2(IndexCategory, ListAction),
|
||||
})
|
||||
queryTestCases = append(queryTestCases, rawTestCase{
|
||||
path: versionalV2(AliasCategory, ListAction),
|
||||
})
|
||||
@ -1020,35 +1026,41 @@ func TestDML(t *testing.T) {
|
||||
queryTestCases := []requestBodyTestCase{}
|
||||
queryTestCases = append(queryTestCases, requestBodyTestCase{
|
||||
path: SearchAction,
|
||||
requestBody: []byte(`{"collectionName": "book", "vector": [0.1, 0.2], "filter": "book_id in [2, 4, 6, 8]", "limit": 4, "outputFields": ["word_count"]}`),
|
||||
requestBody: []byte(`{"collectionName": "book", "vector": [[0.1, 0.2]], "filter": "book_id in [2, 4, 6, 8]", "limit": 4, "outputFields": ["word_count"]}`),
|
||||
})
|
||||
queryTestCases = append(queryTestCases, requestBodyTestCase{
|
||||
path: SearchAction,
|
||||
requestBody: []byte(`{"collectionName": "book", "vector": [0.1, 0.2], "filter": "book_id in [2, 4, 6, 8]", "limit": 4, "outputFields": ["word_count"], "params": {"radius":0.9}}`),
|
||||
requestBody: []byte(`{"collectionName": "book", "vector": [[0.1, 0.2]], "filter": "book_id in [2, 4, 6, 8]", "limit": 4, "outputFields": ["word_count"], "params": {"radius":0.9}}`),
|
||||
})
|
||||
queryTestCases = append(queryTestCases, requestBodyTestCase{
|
||||
path: SearchAction,
|
||||
requestBody: []byte(`{"collectionName": "book", "vector": [0.1, 0.2], "filter": "book_id in [2, 4, 6, 8]", "limit": 4, "outputFields": ["word_count"], "params": {"range_filter": 0.1}}`),
|
||||
requestBody: []byte(`{"collectionName": "book", "vector": [[0.1, 0.2]], "filter": "book_id in [2, 4, 6, 8]", "limit": 4, "outputFields": ["word_count"], "params": {"range_filter": 0.1}}`),
|
||||
errMsg: "can only accept json format request, error: invalid search params",
|
||||
errCode: 1801, // ErrIncorrectParameterFormat
|
||||
})
|
||||
queryTestCases = append(queryTestCases, requestBodyTestCase{
|
||||
path: SearchAction,
|
||||
requestBody: []byte(`{"collectionName": "book", "vector": [0.1, 0.2], "filter": "book_id in [2, 4, 6, 8]", "limit": 4, "outputFields": ["word_count"], "params": {"radius":0.9, "range_filter": 0.1}, "groupingField": "word_count"}`),
|
||||
requestBody: []byte(`{"collectionName": "book", "vector": [[0.1, 0.2]], "filter": "book_id in [2, 4, 6, 8]", "limit": 4, "outputFields": ["word_count"], "params": {"radius":0.9, "range_filter": 0.1}, "groupingField": "word_count"}`),
|
||||
})
|
||||
queryTestCases = append(queryTestCases, requestBodyTestCase{
|
||||
path: SearchAction,
|
||||
requestBody: []byte(`{"collectionName": "book", "vector": [0.1, 0.2], "filter": "book_id in [2, 4, 6, 8]", "limit": 4, "outputFields": ["word_count"], "params": {"radius":0.9, "range_filter": 0.1}, "groupingField": "test"}`),
|
||||
requestBody: []byte(`{"collectionName": "book", "vector": [[0.1, 0.2]], "filter": "book_id in [2, 4, 6, 8]", "limit": 4, "outputFields": ["word_count"], "params": {"radius":0.9, "range_filter": 0.1}, "groupingField": "test"}`),
|
||||
errMsg: "groupBy field not found in schema: field not found[field=test]",
|
||||
errCode: 65535,
|
||||
})
|
||||
queryTestCases = append(queryTestCases, requestBodyTestCase{
|
||||
path: HybridSearchAction,
|
||||
requestBody: []byte(`{"collectionName": "hello_milvus", "search": [{"vector": [0.1, 0.2], "annsField": "float_vector1", "metricType": "L2", "limit": 3}, {"vector": [0.1, 0.2], "annsField": "float_vector2", "metricType": "L2", "limit": 3}], "rerank": {"strategy": "rrf", "params": {"k": 1}}}`),
|
||||
path: SearchAction,
|
||||
requestBody: []byte(`{"collectionName": "book", "vector": [["0.1", "0.2"]], "filter": "book_id in [2, 4, 6, 8]", "limit": 4, "outputFields": ["word_count"], "params": {"radius":0.9, "range_filter": 0.1}, "groupingField": "test"}`),
|
||||
errMsg: "can only accept json format request, error: json: cannot unmarshal string into Go struct field SearchReqV2.vector of type float32",
|
||||
errCode: 1801,
|
||||
})
|
||||
queryTestCases = append(queryTestCases, requestBodyTestCase{
|
||||
path: HybridSearchAction,
|
||||
requestBody: []byte(`{"collectionName": "hello_milvus", "search": [{"vector": [0.1, 0.2], "annsField": "float_vector1", "metricType": "L2", "limit": 3}, {"vector": [0.1, 0.2], "annsField": "float_vector2", "metricType": "L2", "limit": 3}], "rerank": {"strategy": "weighted", "params": {"weights": [0.9, 0.8]}}}`),
|
||||
requestBody: []byte(`{"collectionName": "hello_milvus", "search": [{"vector": [[0.1, 0.2]], "annsField": "float_vector1", "metricType": "L2", "limit": 3}, {"vector": [[0.1, 0.2]], "annsField": "float_vector2", "metricType": "L2", "limit": 3}], "rerank": {"strategy": "rrf", "params": {"k": 1}}}`),
|
||||
})
|
||||
queryTestCases = append(queryTestCases, requestBodyTestCase{
|
||||
path: HybridSearchAction,
|
||||
requestBody: []byte(`{"collectionName": "hello_milvus", "search": [{"vector": [[0.1, 0.2]], "annsField": "float_vector1", "metricType": "L2", "limit": 3}, {"vector": [[0.1, 0.2]], "annsField": "float_vector2", "metricType": "L2", "limit": 3}], "rerank": {"strategy": "weighted", "params": {"weights": [0.9, 0.8]}}}`),
|
||||
})
|
||||
queryTestCases = append(queryTestCases, requestBodyTestCase{
|
||||
path: QueryAction,
|
||||
|
@ -127,13 +127,13 @@ func (req *CollectionDataReq) GetDbName() string { return req.DbName }
|
||||
type SearchReqV2 struct {
|
||||
DbName string `json:"dbName"`
|
||||
CollectionName string `json:"collectionName" binding:"required"`
|
||||
Vector [][]float32 `json:"vector"`
|
||||
PartitionNames []string `json:"partitionNames"`
|
||||
Filter string `json:"filter"`
|
||||
GroupByField string `json:"groupingField"`
|
||||
Limit int32 `json:"limit"`
|
||||
Offset int32 `json:"offset"`
|
||||
OutputFields []string `json:"outputFields"`
|
||||
Vector []float32 `json:"vector"`
|
||||
Params map[string]float64 `json:"params"`
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ type Rand struct {
|
||||
}
|
||||
|
||||
type SubSearchReq struct {
|
||||
Vector []float32 `json:"vector"`
|
||||
Vector [][]float32 `json:"vector"`
|
||||
AnnsField string `json:"annsField"`
|
||||
Filter string `json:"filter"`
|
||||
GroupByField string `json:"groupingField"`
|
||||
|
@ -906,7 +906,8 @@ func serialize(fv []float32) []byte {
|
||||
return data
|
||||
}
|
||||
|
||||
func vector2PlaceholderGroupBytes(vectors []float32) []byte {
|
||||
// todo: support [][]byte for BinaryVector
|
||||
func vectors2PlaceholderGroupBytes(vectors [][]float32) []byte {
|
||||
var placeHolderType commonpb.PlaceholderType
|
||||
ph := &commonpb.PlaceholderValue{
|
||||
Tag: "$0",
|
||||
@ -916,7 +917,9 @@ func vector2PlaceholderGroupBytes(vectors []float32) []byte {
|
||||
placeHolderType = commonpb.PlaceholderType_FloatVector
|
||||
|
||||
ph.Type = placeHolderType
|
||||
ph.Values = append(ph.Values, serialize(vectors))
|
||||
for _, vector := range vectors {
|
||||
ph.Values = append(ph.Values, serialize(vector))
|
||||
}
|
||||
}
|
||||
phg := &commonpb.PlaceholderGroup{
|
||||
Placeholders: []*commonpb.PlaceholderValue{
|
||||
|
@ -490,10 +490,8 @@ func TestInsertWithInt64(t *testing.T) {
|
||||
|
||||
func TestSerialize(t *testing.T) {
|
||||
parameters := []float32{0.11111, 0.22222}
|
||||
// assert.Equal(t, "\ufffd\ufffd\ufffd=\ufffd\ufffdc\u003e", string(serialize(parameters)))
|
||||
// assert.Equal(t, "vector2PlaceholderGroupBytes", string(vector2PlaceholderGroupBytes(parameters))) // todo
|
||||
assert.Equal(t, "\xa4\x8d\xe3=\xa4\x8dc>", string(serialize(parameters)))
|
||||
assert.Equal(t, "\n\x10\n\x02$0\x10e\x1a\b\xa4\x8d\xe3=\xa4\x8dc>", string(vector2PlaceholderGroupBytes(parameters))) // todo
|
||||
assert.Equal(t, "\n\x10\n\x02$0\x10e\x1a\b\xa4\x8d\xe3=\xa4\x8dc>", string(vectors2PlaceholderGroupBytes([][]float32{parameters}))) // todo
|
||||
}
|
||||
|
||||
func compareRow64(m1 map[string]interface{}, m2 map[string]interface{}) bool {
|
||||
|
Loading…
Reference in New Issue
Block a user