diff --git a/internal/distributed/proxy/httpserver/constant.go b/internal/distributed/proxy/httpserver/constant.go index ca38c0297d225..1aece6d66af4f 100644 --- a/internal/distributed/proxy/httpserver/constant.go +++ b/internal/distributed/proxy/httpserver/constant.go @@ -25,16 +25,17 @@ import ( // v2 const ( // --- category --- - DataBaseCategory = "/databases/" - CollectionCategory = "/collections/" - EntityCategory = "/entities/" - PartitionCategory = "/partitions/" - UserCategory = "/users/" - RoleCategory = "/roles/" - IndexCategory = "/indexes/" - AliasCategory = "/aliases/" - ImportJobCategory = "/jobs/import/" - PrivilegeGroupCategory = "/privilege_groups/" + DataBaseCategory = "/databases/" + CollectionCategory = "/collections/" + EntityCategory = "/entities/" + PartitionCategory = "/partitions/" + UserCategory = "/users/" + RoleCategory = "/roles/" + IndexCategory = "/indexes/" + AliasCategory = "/aliases/" + ImportJobCategory = "/jobs/import/" + PrivilegeGroupCategory = "/privilege_groups/" + CollectionFieldCategory = "/collections/fields/" ListAction = "list" HasAction = "has" @@ -45,6 +46,7 @@ const ( LoadStateAction = "get_load_state" RenameAction = "rename" LoadAction = "load" + RefreshLoadAction = "refresh_load" ReleaseAction = "release" QueryAction = "query" GetAction = "get" @@ -63,6 +65,8 @@ const ( GrantPrivilegeActionV2 = "grant_privilege_v2" RevokePrivilegeActionV2 = "revoke_privilege_v2" AlterAction = "alter" + AlterPropertiesAction = "alter_properties" + DropPropertiesAction = "drop_properties" GetProgressAction = "get_progress" // deprecated, keep it for compatibility, use `/v2/vectordb/jobs/import/describe` instead AddPrivilegesToGroupAction = "add_privileges_to_group" RemovePrivilegesFromGroupAction = "remove_privileges_from_group" diff --git a/internal/distributed/proxy/httpserver/handler_v2.go b/internal/distributed/proxy/httpserver/handler_v2.go index dbf76a8bfe17c..fdfc4fea74eab 100644 --- a/internal/distributed/proxy/httpserver/handler_v2.go +++ b/internal/distributed/proxy/httpserver/handler_v2.go @@ -78,7 +78,12 @@ func (h *HandlersV2) RegisterRoutesToV2(router gin.IRouter) { router.POST(CollectionCategory+DropAction, timeoutMiddleware(wrapperPost(func() any { return &CollectionNameReq{} }, wrapperTraceLog(h.dropCollection)))) router.POST(CollectionCategory+RenameAction, timeoutMiddleware(wrapperPost(func() any { return &RenameCollectionReq{} }, wrapperTraceLog(h.renameCollection)))) router.POST(CollectionCategory+LoadAction, timeoutMiddleware(wrapperPost(func() any { return &CollectionNameReq{} }, wrapperTraceLog(h.loadCollection)))) + router.POST(CollectionCategory+RefreshLoadAction, timeoutMiddleware(wrapperPost(func() any { return &CollectionNameReq{} }, wrapperTraceLog(h.refreshLoadCollection)))) router.POST(CollectionCategory+ReleaseAction, timeoutMiddleware(wrapperPost(func() any { return &CollectionNameReq{} }, wrapperTraceLog(h.releaseCollection)))) + router.POST(CollectionCategory+AlterPropertiesAction, timeoutMiddleware(wrapperPost(func() any { return &CollectionReqWithProperties{} }, wrapperTraceLog(h.alterCollectionProperties)))) + router.POST(CollectionCategory+DropPropertiesAction, timeoutMiddleware(wrapperPost(func() any { return &DropCollectionPropertiesReq{} }, wrapperTraceLog(h.dropCollectionProperties)))) + + router.POST(CollectionFieldCategory+AlterPropertiesAction, timeoutMiddleware(wrapperPost(func() any { return &CollectionFieldReqWithParams{} }, wrapperTraceLog(h.alterCollectionFieldProperties)))) router.POST(DataBaseCategory+CreateAction, timeoutMiddleware(wrapperPost(func() any { return &DatabaseReqWithProperties{} }, wrapperTraceLog(h.createDatabase)))) router.POST(DataBaseCategory+DropAction, timeoutMiddleware(wrapperPost(func() any { return &DatabaseReqRequiredName{} }, wrapperTraceLog(h.dropDatabase)))) @@ -170,6 +175,8 @@ func (h *HandlersV2) RegisterRoutesToV2(router gin.IRouter) { router.POST(IndexCategory+CreateAction, timeoutMiddleware(wrapperPost(func() any { return &IndexParamReq{} }, wrapperTraceLog(h.createIndex)))) // todo cannot drop index before release it ? router.POST(IndexCategory+DropAction, timeoutMiddleware(wrapperPost(func() any { return &IndexReq{} }, wrapperTraceLog(h.dropIndex)))) + router.POST(IndexCategory+AlterPropertiesAction, timeoutMiddleware(wrapperPost(func() any { return &IndexReqWithProperties{} }, wrapperTraceLog(h.alterIndexProperties)))) + router.POST(IndexCategory+DropPropertiesAction, timeoutMiddleware(wrapperPost(func() any { return &DropIndexPropertiesReq{} }, wrapperTraceLog(h.dropIndexProperties)))) router.POST(AliasCategory+ListAction, timeoutMiddleware(wrapperPost(func() any { return &OptionalCollectionNameReq{} }, wrapperTraceLog(h.listAlias)))) router.POST(AliasCategory+DescribeAction, timeoutMiddleware(wrapperPost(func() any { return &AliasReq{} }, wrapperTraceLog(h.describeAlias)))) @@ -598,12 +605,26 @@ func (h *HandlersV2) renameCollection(ctx context.Context, c *gin.Context, anyRe return resp, err } +func (h *HandlersV2) refreshLoadCollection(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) { + getter, _ := anyReq.(requestutil.CollectionNameGetter) + req := &milvuspb.LoadCollectionRequest{ + DbName: dbName, + CollectionName: getter.GetCollectionName(), + Refresh: true, + } + return h.loadCollectionInternal(ctx, c, req, dbName) +} + func (h *HandlersV2) loadCollection(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) { getter, _ := anyReq.(requestutil.CollectionNameGetter) req := &milvuspb.LoadCollectionRequest{ DbName: dbName, CollectionName: getter.GetCollectionName(), } + return h.loadCollectionInternal(ctx, c, req, dbName) +} + +func (h *HandlersV2) loadCollectionInternal(ctx context.Context, c *gin.Context, req *milvuspb.LoadCollectionRequest, dbName string) (interface{}, error) { c.Set(ContextRequest, req) resp, err := wrapperProxyWithLimit(ctx, c, req, h.checkAuth, false, "/milvus.proto.milvus.MilvusService/LoadCollection", true, h.proxy, func(reqCtx context.Context, req any) (interface{}, error) { return h.proxy.LoadCollection(reqCtx, req.(*milvuspb.LoadCollectionRequest)) @@ -630,6 +651,68 @@ func (h *HandlersV2) releaseCollection(ctx context.Context, c *gin.Context, anyR return resp, err } +func (h *HandlersV2) alterCollectionProperties(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) { + httpReq := anyReq.(*CollectionReqWithProperties) + req := &milvuspb.AlterCollectionRequest{ + DbName: dbName, + CollectionName: httpReq.CollectionName, + } + properties := make([]*commonpb.KeyValuePair, 0, len(httpReq.Properties)) + for key, value := range httpReq.Properties { + properties = append(properties, &commonpb.KeyValuePair{Key: key, Value: fmt.Sprintf("%v", value)}) + } + req.Properties = properties + + c.Set(ContextRequest, req) + resp, err := wrapperProxyWithLimit(ctx, c, req, h.checkAuth, false, "/milvus.proto.milvus.MilvusService/AlterCollection", true, h.proxy, func(reqCtx context.Context, req any) (interface{}, error) { + return h.proxy.AlterCollection(reqCtx, req.(*milvuspb.AlterCollectionRequest)) + }) + if err == nil { + HTTPReturn(c, http.StatusOK, wrapperReturnDefault()) + } + return resp, err +} + +func (h *HandlersV2) dropCollectionProperties(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) { + httpReq := anyReq.(*DropCollectionPropertiesReq) + req := &milvuspb.AlterCollectionRequest{ + DbName: dbName, + CollectionName: httpReq.CollectionName, + DeleteKeys: httpReq.DeleteKeys, + } + c.Set(ContextRequest, req) + resp, err := wrapperProxyWithLimit(ctx, c, req, h.checkAuth, false, "/milvus.proto.milvus.MilvusService/AlterCollection", true, h.proxy, func(reqCtx context.Context, req any) (interface{}, error) { + return h.proxy.AlterCollection(reqCtx, req.(*milvuspb.AlterCollectionRequest)) + }) + if err == nil { + HTTPReturn(c, http.StatusOK, wrapperReturnDefault()) + } + return resp, err +} + +func (h *HandlersV2) alterCollectionFieldProperties(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) { + httpReq := anyReq.(*CollectionFieldReqWithParams) + req := &milvuspb.AlterCollectionFieldRequest{ + DbName: dbName, + CollectionName: httpReq.CollectionName, + FieldName: httpReq.FieldName, + } + properties := make([]*commonpb.KeyValuePair, 0, len(httpReq.FieldParams)) + for key, value := range httpReq.FieldParams { + properties = append(properties, &commonpb.KeyValuePair{Key: key, Value: fmt.Sprintf("%v", value)}) + } + req.Properties = properties + + c.Set(ContextRequest, req) + resp, err := wrapperProxyWithLimit(ctx, c, req, h.checkAuth, false, "/milvus.proto.milvus.MilvusService/AlterCollectionField", true, h.proxy, func(reqCtx context.Context, req any) (interface{}, error) { + return h.proxy.AlterCollectionField(reqCtx, req.(*milvuspb.AlterCollectionFieldRequest)) + }) + if err == nil { + HTTPReturn(c, http.StatusOK, wrapperReturnDefault()) + } + return resp, err +} + // copy from internal/proxy/task_query.go func matchCountRule(outputs []string) bool { return len(outputs) == 1 && strings.ToLower(strings.TrimSpace(outputs[0])) == "count(*)" @@ -2144,6 +2227,45 @@ func (h *HandlersV2) dropIndex(ctx context.Context, c *gin.Context, anyReq any, return resp, err } +func (h *HandlersV2) alterIndexProperties(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) { + httpReq := anyReq.(*IndexReqWithProperties) + req := &milvuspb.AlterIndexRequest{ + DbName: dbName, + CollectionName: httpReq.CollectionName, + } + extraParams := make([]*commonpb.KeyValuePair, 0, len(httpReq.Properties)) + for key, value := range httpReq.Properties { + extraParams = append(extraParams, &commonpb.KeyValuePair{Key: key, Value: fmt.Sprintf("%v", value)}) + } + req.ExtraParams = extraParams + + c.Set(ContextRequest, req) + resp, err := wrapperProxyWithLimit(ctx, c, req, h.checkAuth, false, "/milvus.proto.milvus.MilvusService/AlterIndex", true, h.proxy, func(reqCtx context.Context, req any) (interface{}, error) { + return h.proxy.AlterIndex(reqCtx, req.(*milvuspb.AlterIndexRequest)) + }) + if err == nil { + HTTPReturn(c, http.StatusOK, wrapperReturnDefault()) + } + return resp, err +} + +func (h *HandlersV2) dropIndexProperties(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) { + httpReq := anyReq.(*DropIndexPropertiesReq) + req := &milvuspb.AlterIndexRequest{ + DbName: dbName, + CollectionName: httpReq.CollectionName, + DeleteKeys: httpReq.DeleteKeys, + } + c.Set(ContextRequest, req) + resp, err := wrapperProxyWithLimit(ctx, c, req, h.checkAuth, false, "/milvus.proto.milvus.MilvusService/AlterIndex", true, h.proxy, func(reqCtx context.Context, req any) (interface{}, error) { + return h.proxy.AlterIndex(reqCtx, req.(*milvuspb.AlterIndexRequest)) + }) + if err == nil { + HTTPReturn(c, http.StatusOK, wrapperReturnDefault()) + } + return resp, err +} + func (h *HandlersV2) listAlias(ctx context.Context, c *gin.Context, anyReq any, dbName string) (interface{}, error) { collectionGetter, _ := anyReq.(requestutil.CollectionNameGetter) req := &milvuspb.ListAliasesRequest{ diff --git a/internal/distributed/proxy/httpserver/handler_v2_test.go b/internal/distributed/proxy/httpserver/handler_v2_test.go index 0e8211f993812..b8f146ed1be32 100644 --- a/internal/distributed/proxy/httpserver/handler_v2_test.go +++ b/internal/distributed/proxy/httpserver/handler_v2_test.go @@ -802,6 +802,187 @@ func TestDatabase(t *testing.T) { } } +func TestColletcionProperties(t *testing.T) { + paramtable.Init() + // disable rate limit + paramtable.Get().Save(paramtable.Get().QuotaConfig.QuotaAndLimitsEnabled.Key, "false") + defer paramtable.Get().Reset(paramtable.Get().QuotaConfig.QuotaAndLimitsEnabled.Key) + + postTestCases := []requestBodyTestCase{} + mp := mocks.NewMockProxy(t) + mp.EXPECT().AlterCollection(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Once() + mp.EXPECT().AlterCollection(mock.Anything, mock.Anything).Return( + &commonpb.Status{ + Code: 1100, + Reason: "mock", + }, nil).Once() + testEngine := initHTTPServerV2(mp, false) + path := versionalV2(CollectionCategory, AlterPropertiesAction) + // success + postTestCases = append(postTestCases, requestBodyTestCase{ + path: path, + requestBody: []byte(`{"collectionName":"test", "properties":{"mmap": true}}`), + }) + // mock fail + postTestCases = append(postTestCases, requestBodyTestCase{ + path: path, + requestBody: []byte(`{"collectionName":"mock", "properties":{"mmap": true}}`), + errMsg: "mock", + errCode: 1100, // ErrParameterInvalid + }) + + mp.EXPECT().AlterCollection(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Once() + mp.EXPECT().AlterCollection(mock.Anything, mock.Anything).Return( + &commonpb.Status{ + Code: 1100, + Reason: "mock", + }, nil).Once() + path = versionalV2(CollectionCategory, DropPropertiesAction) + // success + postTestCases = append(postTestCases, requestBodyTestCase{ + path: path, + requestBody: []byte(`{"collectionName":"test", "deleteKeys":["mmap"]}`), + }) + // mock fail + postTestCases = append(postTestCases, requestBodyTestCase{ + path: path, + requestBody: []byte(`{"collectionName":"mock", "deleteKeys":["mmap"]}`), + errMsg: "mock", + errCode: 1100, // ErrParameterInvalid + }) + + for _, testcase := range postTestCases { + t.Run("post"+testcase.path, func(t *testing.T) { + req := httptest.NewRequest(http.MethodPost, testcase.path, bytes.NewReader(testcase.requestBody)) + w := httptest.NewRecorder() + testEngine.ServeHTTP(w, req) + assert.Equal(t, http.StatusOK, w.Code) + fmt.Println(w.Body.String()) + returnBody := &ReturnErrMsg{} + err := json.Unmarshal(w.Body.Bytes(), returnBody) + assert.Nil(t, err) + assert.Equal(t, testcase.errCode, returnBody.Code) + if testcase.errCode != 0 { + assert.Equal(t, testcase.errMsg, returnBody.Message) + } + }) + } +} + +func TestIndexProperties(t *testing.T) { + paramtable.Init() + // disable rate limit + paramtable.Get().Save(paramtable.Get().QuotaConfig.QuotaAndLimitsEnabled.Key, "false") + defer paramtable.Get().Reset(paramtable.Get().QuotaConfig.QuotaAndLimitsEnabled.Key) + + postTestCases := []requestBodyTestCase{} + mp := mocks.NewMockProxy(t) + mp.EXPECT().AlterIndex(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Once() + mp.EXPECT().AlterIndex(mock.Anything, mock.Anything).Return( + &commonpb.Status{ + Code: 1100, + Reason: "mock", + }, nil).Once() + testEngine := initHTTPServerV2(mp, false) + path := versionalV2(IndexCategory, AlterPropertiesAction) + // success + postTestCases = append(postTestCases, requestBodyTestCase{ + path: path, + requestBody: []byte(`{"collectionName":"test", "indexName":"test", "properties":{"mmap": true}}`), + }) + // mock fail + postTestCases = append(postTestCases, requestBodyTestCase{ + path: path, + requestBody: []byte(`{"collectionName":"mock", "indexName":"test", "properties":{"mmap": true}}`), + errMsg: "mock", + errCode: 1100, // ErrParameterInvalid + }) + + mp.EXPECT().AlterIndex(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Once() + mp.EXPECT().AlterIndex(mock.Anything, mock.Anything).Return( + &commonpb.Status{ + Code: 1100, + Reason: "mock", + }, nil).Once() + path = versionalV2(IndexCategory, DropPropertiesAction) + // success + postTestCases = append(postTestCases, requestBodyTestCase{ + path: path, + requestBody: []byte(`{"collectionName":"test","indexName":"test", "deleteKeys":["test"]}`), + }) + // mock fail + postTestCases = append(postTestCases, requestBodyTestCase{ + path: path, + requestBody: []byte(`{"collectionName":"mock","indexName":"test", "deleteKeys":["test"]}`), + errMsg: "mock", + errCode: 1100, // ErrParameterInvalid + }) + + for _, testcase := range postTestCases { + t.Run("post"+testcase.path, func(t *testing.T) { + req := httptest.NewRequest(http.MethodPost, testcase.path, bytes.NewReader(testcase.requestBody)) + w := httptest.NewRecorder() + testEngine.ServeHTTP(w, req) + assert.Equal(t, http.StatusOK, w.Code) + fmt.Println(w.Body.String()) + returnBody := &ReturnErrMsg{} + err := json.Unmarshal(w.Body.Bytes(), returnBody) + assert.Nil(t, err) + assert.Equal(t, testcase.errCode, returnBody.Code) + if testcase.errCode != 0 { + assert.Equal(t, testcase.errMsg, returnBody.Message) + } + }) + } +} + +func TestCollectionFieldProperties(t *testing.T) { + paramtable.Init() + // disable rate limit + paramtable.Get().Save(paramtable.Get().QuotaConfig.QuotaAndLimitsEnabled.Key, "false") + defer paramtable.Get().Reset(paramtable.Get().QuotaConfig.QuotaAndLimitsEnabled.Key) + + postTestCases := []requestBodyTestCase{} + mp := mocks.NewMockProxy(t) + mp.EXPECT().AlterCollectionField(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Once() + mp.EXPECT().AlterCollectionField(mock.Anything, mock.Anything).Return( + &commonpb.Status{ + Code: 1100, + Reason: "mock", + }, nil).Once() + testEngine := initHTTPServerV2(mp, false) + path := versionalV2(CollectionFieldCategory, AlterPropertiesAction) + // success + postTestCases = append(postTestCases, requestBodyTestCase{ + path: path, + requestBody: []byte(`{"collectionName":"test", "fieldName":"test", "fieldParams":{"max_length": 100}}`), + }) + // mock fail + postTestCases = append(postTestCases, requestBodyTestCase{ + path: path, + requestBody: []byte(`{"collectionName":"mock", "fieldName":"test", "fieldParams":{"max_length": 100}}`), + errMsg: "mock", + errCode: 1100, // ErrParameterInvalid + }) + + for _, testcase := range postTestCases { + t.Run("post"+testcase.path, func(t *testing.T) { + req := httptest.NewRequest(http.MethodPost, testcase.path, bytes.NewReader(testcase.requestBody)) + w := httptest.NewRecorder() + testEngine.ServeHTTP(w, req) + assert.Equal(t, http.StatusOK, w.Code) + fmt.Println(w.Body.String()) + returnBody := &ReturnErrMsg{} + err := json.Unmarshal(w.Body.Bytes(), returnBody) + assert.Nil(t, err) + assert.Equal(t, testcase.errCode, returnBody.Code) + if testcase.errCode != 0 { + assert.Equal(t, testcase.errMsg, returnBody.Message) + } + }) + } +} + func TestCreateCollection(t *testing.T) { paramtable.Init() // disable rate limit @@ -1482,7 +1663,7 @@ func TestMethodPost(t *testing.T) { mp := mocks.NewMockProxy(t) mp.EXPECT().CreateCollection(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Once() mp.EXPECT().RenameCollection(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Once() - mp.EXPECT().LoadCollection(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Twice() + mp.EXPECT().LoadCollection(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Times(3) mp.EXPECT().ReleaseCollection(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Once() mp.EXPECT().CreatePartition(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Once() mp.EXPECT().LoadPartitions(mock.Anything, mock.Anything).Return(commonSuccessStatus, nil).Once() @@ -1532,6 +1713,9 @@ func TestMethodPost(t *testing.T) { queryTestCases = append(queryTestCases, rawTestCase{ path: versionalV2(CollectionCategory, LoadAction), }) + queryTestCases = append(queryTestCases, rawTestCase{ + path: versionalV2(CollectionCategory, RefreshLoadAction), + }) queryTestCases = append(queryTestCases, rawTestCase{ path: versionalV2(CollectionCategory, ReleaseAction), }) diff --git a/internal/distributed/proxy/httpserver/request_v2.go b/internal/distributed/proxy/httpserver/request_v2.go index 833686825256d..4231c7acd8b2f 100644 --- a/internal/distributed/proxy/httpserver/request_v2.go +++ b/internal/distributed/proxy/httpserver/request_v2.go @@ -66,6 +66,18 @@ func (req *CollectionNameReq) GetPartitionNames() []string { return req.PartitionNames } +type CollectionReqWithProperties struct { + DbName string `json:"dbName"` + CollectionName string `json:"collectionName" binding:"required"` + Properties map[string]interface{} `json:"properties"` +} + +func (req *CollectionReqWithProperties) GetDbName() string { return req.DbName } + +func (req *CollectionReqWithProperties) GetCollectionName() string { + return req.CollectionName +} + type OptionalCollectionNameReq struct { DbName string `json:"dbName"` CollectionName string `json:"collectionName"` @@ -88,6 +100,35 @@ type RenameCollectionReq struct { func (req *RenameCollectionReq) GetDbName() string { return req.DbName } +type DropCollectionPropertiesReq struct { + DbName string `json:"dbName"` + CollectionName string `json:"collectionName" binding:"required"` + DeleteKeys []string `json:"deleteKeys"` +} + +func (req *DropCollectionPropertiesReq) GetDbName() string { return req.DbName } + +func (req *DropCollectionPropertiesReq) GetCollectionName() string { + return req.CollectionName +} + +type CollectionFieldReqWithParams struct { + DbName string `json:"dbName"` + CollectionName string `json:"collectionName" binding:"required"` + FieldName string `json:"fieldName" binding:"required"` + FieldParams map[string]interface{} `json:"fieldParams"` +} + +func (req *CollectionFieldReqWithParams) GetDbName() string { return req.DbName } + +func (req *CollectionFieldReqWithParams) GetCollectionName() string { + return req.CollectionName +} + +func (req *CollectionFieldReqWithParams) GetFieldName() string { + return req.FieldName +} + type PartitionReq struct { // CollectionNameReq DbName string `json:"dbName"` @@ -364,6 +405,40 @@ func (req *IndexReq) GetIndexName() string { return req.IndexName } +type IndexReqWithProperties struct { + DbName string `json:"dbName"` + CollectionName string `json:"collectionName" binding:"required"` + IndexName string `json:"indexName" binding:"required"` + Properties map[string]interface{} `json:"properties"` +} + +func (req *IndexReqWithProperties) GetDbName() string { return req.DbName } + +func (req *IndexReqWithProperties) GetCollectionName() string { + return req.CollectionName +} + +func (req *IndexReqWithProperties) GetIndexName() string { + return req.IndexName +} + +type DropIndexPropertiesReq struct { + DbName string `json:"dbName"` + CollectionName string `json:"collectionName" binding:"required"` + IndexName string `json:"indexName" binding:"required"` + DeleteKeys []string `json:"deleteKeys"` +} + +func (req *DropIndexPropertiesReq) GetDbName() string { return req.DbName } + +func (req *DropIndexPropertiesReq) GetCollectionName() string { + return req.CollectionName +} + +func (req *DropIndexPropertiesReq) GetIndexName() string { + return req.IndexName +} + type FieldSchema struct { FieldName string `json:"fieldName" binding:"required"` DataType string `json:"dataType" binding:"required"`