mirror of https://github.com/milvus-io/milvus.git
add a custom http header: Accept-Type-Allow-Int64 (#28125)
Signed-off-by: PowderLi <min.li@zilliz.com>pull/28195/head
parent
87e8d04ed7
commit
43db873770
|
@ -347,7 +347,7 @@ MinioChunkManager::Remove(const std::string& filepath) {
|
|||
|
||||
std::vector<std::string>
|
||||
MinioChunkManager::ListWithPrefix(const std::string& filepath) {
|
||||
return ListObjects(default_bucket_name_.c_str(), filepath.c_str());
|
||||
return ListObjects(default_bucket_name_, filepath);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
|
@ -393,7 +393,7 @@ MinioChunkManager::ListBuckets() {
|
|||
ThrowS3Error("ListBuckets", err, "params");
|
||||
}
|
||||
for (auto&& b : outcome.GetResult().GetBuckets()) {
|
||||
buckets.emplace_back(b.GetName().c_str());
|
||||
buckets.emplace_back(b.GetName());
|
||||
}
|
||||
return buckets;
|
||||
}
|
||||
|
@ -623,7 +623,7 @@ MinioChunkManager::ListObjects(const std::string& bucket_name,
|
|||
}
|
||||
auto objects = outcome.GetResult().GetContents();
|
||||
for (auto& obj : objects) {
|
||||
objects_vec.emplace_back(obj.GetKey().c_str());
|
||||
objects_vec.emplace_back(obj.GetKey());
|
||||
}
|
||||
return objects_vec;
|
||||
}
|
||||
|
|
|
@ -19,15 +19,15 @@ const (
|
|||
EnableAutoID = true
|
||||
DisableAutoID = false
|
||||
|
||||
HTTPCollectionName = "collectionName"
|
||||
HTTPDbName = "dbName"
|
||||
DefaultDbName = "default"
|
||||
DefaultIndexName = "vector_idx"
|
||||
DefaultOutputFields = "*"
|
||||
|
||||
HTTPReturnCode = "code"
|
||||
HTTPReturnMessage = "message"
|
||||
HTTPReturnData = "data"
|
||||
HTTPCollectionName = "collectionName"
|
||||
HTTPDbName = "dbName"
|
||||
DefaultDbName = "default"
|
||||
DefaultIndexName = "vector_idx"
|
||||
DefaultOutputFields = "*"
|
||||
HTTPHeaderAllowInt64 = "Accept-Type-Allow-Int64"
|
||||
HTTPReturnCode = "code"
|
||||
HTTPReturnMessage = "message"
|
||||
HTTPReturnData = "data"
|
||||
|
||||
HTTPReturnFieldName = "name"
|
||||
HTTPReturnFieldType = "type"
|
||||
|
|
|
@ -54,7 +54,10 @@ func (h *Handlers) checkDatabase(ctx context.Context, c *gin.Context, dbName str
|
|||
return true
|
||||
}
|
||||
}
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrDatabaseNotFound), HTTPReturnMessage: merr.ErrDatabaseNotFound.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrDatabaseNotFound),
|
||||
HTTPReturnMessage: merr.ErrDatabaseNotFound.Error() + ", database: " + dbName,
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -152,12 +155,18 @@ func (h *Handlers) createCollection(c *gin.Context) {
|
|||
}
|
||||
if err := c.ShouldBindBodyWith(&httpReq, binding.JSON); err != nil {
|
||||
log.Warn("high level restful api, the parameter of create collection is incorrect", zap.Any("request", httpReq), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat), HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat),
|
||||
HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
if httpReq.CollectionName == "" || httpReq.Dimension == 0 {
|
||||
log.Warn("high level restful api, create collection require parameters: [collectionName, dimension], but miss", zap.Any("request", httpReq))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters), HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters),
|
||||
HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error() + ", required parameters: [collectionName, dimension]",
|
||||
})
|
||||
return
|
||||
}
|
||||
schema, err := proto.Marshal(&schemapb.CollectionSchema{
|
||||
|
@ -189,7 +198,10 @@ func (h *Handlers) createCollection(c *gin.Context) {
|
|||
})
|
||||
if err != nil {
|
||||
log.Warn("high level restful api, marshal collection schema fail", zap.Any("request", httpReq), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrMarshalCollectionSchema), HTTPReturnMessage: merr.ErrMarshalCollectionSchema.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrMarshalCollectionSchema),
|
||||
HTTPReturnMessage: merr.ErrMarshalCollectionSchema.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
req := milvuspb.CreateCollectionRequest{
|
||||
|
@ -248,7 +260,10 @@ func (h *Handlers) getCollectionDetails(c *gin.Context) {
|
|||
collectionName := c.Query(HTTPCollectionName)
|
||||
if collectionName == "" {
|
||||
log.Warn("high level restful api, desc collection require parameter: [collectionName], but miss")
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters), HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters),
|
||||
HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error() + ", required parameters: [collectionName]",
|
||||
})
|
||||
return
|
||||
}
|
||||
dbName := c.DefaultQuery(HTTPDbName, DefaultDbName)
|
||||
|
@ -320,12 +335,18 @@ func (h *Handlers) dropCollection(c *gin.Context) {
|
|||
}
|
||||
if err := c.ShouldBindBodyWith(&httpReq, binding.JSON); err != nil {
|
||||
log.Warn("high level restful api, the parameter of drop collection is incorrect", zap.Any("request", httpReq), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat), HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat),
|
||||
HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
if httpReq.CollectionName == "" {
|
||||
log.Warn("high level restful api, drop collection require parameter: [collectionName], but miss")
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters), HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters),
|
||||
HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error() + ", required parameters: [collectionName]",
|
||||
})
|
||||
return
|
||||
}
|
||||
req := milvuspb.DropCollectionRequest{
|
||||
|
@ -345,7 +366,10 @@ func (h *Handlers) dropCollection(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
if !has {
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrCollectionNotFound), HTTPReturnMessage: merr.ErrCollectionNotFound.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrCollectionNotFound),
|
||||
HTTPReturnMessage: merr.ErrCollectionNotFound.Error() + ", database: " + httpReq.DbName + ", collection: " + httpReq.CollectionName,
|
||||
})
|
||||
return
|
||||
}
|
||||
response, err := h.proxy.DropCollection(ctx, &req)
|
||||
|
@ -367,12 +391,18 @@ func (h *Handlers) query(c *gin.Context) {
|
|||
}
|
||||
if err := c.ShouldBindBodyWith(&httpReq, binding.JSON); err != nil {
|
||||
log.Warn("high level restful api, the parameter of query is incorrect", zap.Any("request", httpReq), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat), HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat),
|
||||
HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
if httpReq.CollectionName == "" || httpReq.Filter == "" {
|
||||
log.Warn("high level restful api, query require parameter: [collectionName, filter], but miss")
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters), HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters),
|
||||
HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error() + ", required parameters: [collectionName, filter]",
|
||||
})
|
||||
return
|
||||
}
|
||||
req := milvuspb.QueryRequest{
|
||||
|
@ -404,10 +434,14 @@ func (h *Handlers) query(c *gin.Context) {
|
|||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(err), HTTPReturnMessage: err.Error()})
|
||||
} else {
|
||||
outputData, err := buildQueryResp(int64(0), response.OutputFields, response.FieldsData, nil, nil)
|
||||
allowJS, _ := strconv.ParseBool(c.Request.Header.Get(HTTPHeaderAllowInt64))
|
||||
outputData, err := buildQueryResp(int64(0), response.OutputFields, response.FieldsData, nil, nil, allowJS)
|
||||
if err != nil {
|
||||
log.Warn("high level restful api, fail to deal with query result", zap.Any("response", response), zap.Error(err))
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrInvalidSearchResult), HTTPReturnMessage: merr.ErrInvalidSearchResult.Error()})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrInvalidSearchResult),
|
||||
HTTPReturnMessage: merr.ErrInvalidSearchResult.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: outputData})
|
||||
}
|
||||
|
@ -421,12 +455,18 @@ func (h *Handlers) get(c *gin.Context) {
|
|||
}
|
||||
if err := c.ShouldBindBodyWith(&httpReq, binding.JSON); err != nil {
|
||||
log.Warn("high level restful api, the parameter of get is incorrect", zap.Any("request", httpReq), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat), HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat),
|
||||
HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
if httpReq.CollectionName == "" || httpReq.ID == nil {
|
||||
log.Warn("high level restful api, get require parameter: [collectionName, id], but miss")
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters), HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters),
|
||||
HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error() + ", required parameters: [collectionName, id]",
|
||||
})
|
||||
return
|
||||
}
|
||||
req := milvuspb.QueryRequest{
|
||||
|
@ -450,7 +490,10 @@ func (h *Handlers) get(c *gin.Context) {
|
|||
body, _ := c.Get(gin.BodyBytesKey)
|
||||
filter, err := checkGetPrimaryKey(coll.Schema, gjson.Get(string(body.([]byte)), DefaultPrimaryFieldName))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrCheckPrimaryKey), HTTPReturnMessage: merr.ErrCheckPrimaryKey.Error()})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrCheckPrimaryKey),
|
||||
HTTPReturnMessage: merr.ErrCheckPrimaryKey.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
req.Expr = filter
|
||||
|
@ -461,13 +504,16 @@ func (h *Handlers) get(c *gin.Context) {
|
|||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(err), HTTPReturnMessage: err.Error()})
|
||||
} else {
|
||||
outputData, err := buildQueryResp(int64(0), response.OutputFields, response.FieldsData, nil, nil)
|
||||
allowJS, _ := strconv.ParseBool(c.Request.Header.Get(HTTPHeaderAllowInt64))
|
||||
outputData, err := buildQueryResp(int64(0), response.OutputFields, response.FieldsData, nil, nil, allowJS)
|
||||
if err != nil {
|
||||
log.Warn("high level restful api, fail to deal with get result", zap.Any("response", response), zap.Error(err))
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrInvalidSearchResult), HTTPReturnMessage: merr.ErrInvalidSearchResult.Error()})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrInvalidSearchResult),
|
||||
HTTPReturnMessage: merr.ErrInvalidSearchResult.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: outputData})
|
||||
log.Error("get resultIS: ", zap.Any("res", outputData))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -478,12 +524,18 @@ func (h *Handlers) delete(c *gin.Context) {
|
|||
}
|
||||
if err := c.ShouldBindBodyWith(&httpReq, binding.JSON); err != nil {
|
||||
log.Warn("high level restful api, the parameter of delete is incorrect", zap.Any("request", httpReq), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat), HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat),
|
||||
HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
if httpReq.CollectionName == "" || (httpReq.ID == nil && httpReq.Filter == "") {
|
||||
log.Warn("high level restful api, delete require parameter: [collectionName, id/filter], but miss")
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters), HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters),
|
||||
HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error() + ", required parameters: [collectionName, id/filter]",
|
||||
})
|
||||
return
|
||||
}
|
||||
req := milvuspb.DeleteRequest{
|
||||
|
@ -507,7 +559,10 @@ func (h *Handlers) delete(c *gin.Context) {
|
|||
body, _ := c.Get(gin.BodyBytesKey)
|
||||
filter, err := checkGetPrimaryKey(coll.Schema, gjson.Get(string(body.([]byte)), DefaultPrimaryFieldName))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrCheckPrimaryKey), HTTPReturnMessage: merr.ErrCheckPrimaryKey.Error()})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrCheckPrimaryKey),
|
||||
HTTPReturnMessage: merr.ErrCheckPrimaryKey.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
req.Expr = filter
|
||||
|
@ -533,7 +588,10 @@ func (h *Handlers) insert(c *gin.Context) {
|
|||
}
|
||||
if err = c.ShouldBindBodyWith(&singleInsertReq, binding.JSON); err != nil {
|
||||
log.Warn("high level restful api, the parameter of insert is incorrect", zap.Any("request", httpReq), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat), HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat),
|
||||
HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
httpReq.DbName = singleInsertReq.DbName
|
||||
|
@ -542,7 +600,10 @@ func (h *Handlers) insert(c *gin.Context) {
|
|||
}
|
||||
if httpReq.CollectionName == "" || httpReq.Data == nil {
|
||||
log.Warn("high level restful api, insert require parameter: [collectionName, data], but miss")
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters), HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters),
|
||||
HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error() + ", required parameters: [collectionName, data]",
|
||||
})
|
||||
return
|
||||
}
|
||||
req := milvuspb.InsertRequest{
|
||||
|
@ -567,13 +628,19 @@ func (h *Handlers) insert(c *gin.Context) {
|
|||
err, httpReq.Data = checkAndSetData(string(body.([]byte)), coll)
|
||||
if err != nil {
|
||||
log.Warn("high level restful api, fail to deal with insert data", zap.Any("body", body), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrInvalidInsertData), HTTPReturnMessage: merr.ErrInvalidInsertData.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrInvalidInsertData),
|
||||
HTTPReturnMessage: merr.ErrInvalidInsertData.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
req.FieldsData, err = anyToColumns(httpReq.Data, coll.Schema)
|
||||
if err != nil {
|
||||
log.Warn("high level restful api, fail to deal with insert data", zap.Any("data", httpReq.Data), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrInvalidInsertData), HTTPReturnMessage: merr.ErrInvalidInsertData.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrInvalidInsertData),
|
||||
HTTPReturnMessage: merr.ErrInvalidInsertData.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
response, err := h.proxy.Insert(ctx, &req)
|
||||
|
@ -585,11 +652,19 @@ func (h *Handlers) insert(c *gin.Context) {
|
|||
} else {
|
||||
switch response.IDs.GetIdField().(type) {
|
||||
case *schemapb.IDs_IntId:
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: gin.H{"insertCount": response.InsertCnt, "insertIds": response.IDs.IdField.(*schemapb.IDs_IntId).IntId.Data}})
|
||||
allowJS, _ := strconv.ParseBool(c.Request.Header.Get(HTTPHeaderAllowInt64))
|
||||
if allowJS {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: gin.H{"insertCount": response.InsertCnt, "insertIds": response.IDs.IdField.(*schemapb.IDs_IntId).IntId.Data}})
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: gin.H{"insertCount": response.InsertCnt, "insertIds": formatInt64(response.IDs.IdField.(*schemapb.IDs_IntId).IntId.Data)}})
|
||||
}
|
||||
case *schemapb.IDs_StrId:
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: gin.H{"insertCount": response.InsertCnt, "insertIds": response.IDs.IdField.(*schemapb.IDs_StrId).StrId.Data}})
|
||||
default:
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrCheckPrimaryKey), HTTPReturnMessage: merr.ErrCheckPrimaryKey.Error()})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrCheckPrimaryKey),
|
||||
HTTPReturnMessage: merr.ErrCheckPrimaryKey.Error() + ", error: unsupported primary key data type",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -603,8 +678,11 @@ func (h *Handlers) upsert(c *gin.Context) {
|
|||
DbName: DefaultDbName,
|
||||
}
|
||||
if err = c.ShouldBindBodyWith(&singleUpsertReq, binding.JSON); err != nil {
|
||||
log.Warn("high level restful api, the parameter of insert is incorrect", zap.Any("request", httpReq), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat), HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error()})
|
||||
log.Warn("high level restful api, the parameter of upsert is incorrect", zap.Any("request", httpReq), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat),
|
||||
HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
httpReq.DbName = singleUpsertReq.DbName
|
||||
|
@ -612,8 +690,11 @@ func (h *Handlers) upsert(c *gin.Context) {
|
|||
httpReq.Data = []map[string]interface{}{singleUpsertReq.Data}
|
||||
}
|
||||
if httpReq.CollectionName == "" || httpReq.Data == nil {
|
||||
log.Warn("high level restful api, insert require parameter: [collectionName, data], but miss")
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters), HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error()})
|
||||
log.Warn("high level restful api, upsert require parameter: [collectionName, data], but miss")
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters),
|
||||
HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error() + ", required parameters: [collectionName, data]",
|
||||
})
|
||||
return
|
||||
}
|
||||
req := milvuspb.UpsertRequest{
|
||||
|
@ -642,14 +723,20 @@ func (h *Handlers) upsert(c *gin.Context) {
|
|||
body, _ := c.Get(gin.BodyBytesKey)
|
||||
err, httpReq.Data = checkAndSetData(string(body.([]byte)), coll)
|
||||
if err != nil {
|
||||
log.Warn("high level restful api, fail to deal with insert data", zap.Any("body", body), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrInvalidInsertData), HTTPReturnMessage: merr.ErrInvalidInsertData.Error()})
|
||||
log.Warn("high level restful api, fail to deal with upsert data", zap.Any("body", body), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrInvalidInsertData),
|
||||
HTTPReturnMessage: merr.ErrInvalidInsertData.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
req.FieldsData, err = anyToColumns(httpReq.Data, coll.Schema)
|
||||
if err != nil {
|
||||
log.Warn("high level restful api, fail to deal with insert data", zap.Any("data", httpReq.Data), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrInvalidInsertData), HTTPReturnMessage: merr.ErrInvalidInsertData.Error()})
|
||||
log.Warn("high level restful api, fail to deal with upsert data", zap.Any("data", httpReq.Data), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrInvalidInsertData),
|
||||
HTTPReturnMessage: merr.ErrInvalidInsertData.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
response, err := h.proxy.Upsert(ctx, &req)
|
||||
|
@ -661,11 +748,19 @@ func (h *Handlers) upsert(c *gin.Context) {
|
|||
} else {
|
||||
switch response.IDs.GetIdField().(type) {
|
||||
case *schemapb.IDs_IntId:
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: gin.H{"upsertCount": response.UpsertCnt, "upsertIds": response.IDs.IdField.(*schemapb.IDs_IntId).IntId.Data}})
|
||||
allowJS, _ := strconv.ParseBool(c.Request.Header.Get(HTTPHeaderAllowInt64))
|
||||
if allowJS {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: gin.H{"upsertCount": response.UpsertCnt, "upsertIds": response.IDs.IdField.(*schemapb.IDs_IntId).IntId.Data}})
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: gin.H{"upsertCount": response.UpsertCnt, "upsertIds": formatInt64(response.IDs.IdField.(*schemapb.IDs_IntId).IntId.Data)}})
|
||||
}
|
||||
case *schemapb.IDs_StrId:
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: gin.H{"upsertCount": response.UpsertCnt, "upsertIds": response.IDs.IdField.(*schemapb.IDs_StrId).StrId.Data}})
|
||||
default:
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrCheckPrimaryKey), HTTPReturnMessage: merr.ErrCheckPrimaryKey.Error()})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrCheckPrimaryKey),
|
||||
HTTPReturnMessage: merr.ErrCheckPrimaryKey.Error() + ", error: unsupported primary key data type",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -677,12 +772,18 @@ func (h *Handlers) search(c *gin.Context) {
|
|||
}
|
||||
if err := c.ShouldBindBodyWith(&httpReq, binding.JSON); err != nil {
|
||||
log.Warn("high level restful api, the parameter of search is incorrect", zap.Any("request", httpReq), zap.Error(err))
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat), HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrIncorrectParameterFormat),
|
||||
HTTPReturnMessage: merr.ErrIncorrectParameterFormat.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
if httpReq.CollectionName == "" || httpReq.Vector == nil {
|
||||
log.Warn("high level restful api, search require parameter: [collectionName, vector], but miss")
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters), HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error()})
|
||||
c.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrMissingRequiredParameters),
|
||||
HTTPReturnMessage: merr.ErrMissingRequiredParameters.Error() + ", required parameters: [collectionName, vector]",
|
||||
})
|
||||
return
|
||||
}
|
||||
params := map[string]interface{}{ // auto generated mapping
|
||||
|
@ -724,10 +825,14 @@ func (h *Handlers) search(c *gin.Context) {
|
|||
if response.Results.TopK == int64(0) {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: []interface{}{}})
|
||||
} else {
|
||||
outputData, err := buildQueryResp(response.Results.TopK, response.Results.OutputFields, response.Results.FieldsData, response.Results.Ids, response.Results.Scores)
|
||||
allowJS, _ := strconv.ParseBool(c.Request.Header.Get(HTTPHeaderAllowInt64))
|
||||
outputData, err := buildQueryResp(response.Results.TopK, response.Results.OutputFields, response.Results.FieldsData, response.Results.Ids, response.Results.Scores, allowJS)
|
||||
if err != nil {
|
||||
log.Warn("high level restful api, fail to deal with search result", zap.Any("result", response.Results), zap.Error(err))
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: merr.Code(merr.ErrInvalidSearchResult), HTTPReturnMessage: merr.ErrInvalidSearchResult.Error()})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
HTTPReturnCode: merr.Code(merr.ErrInvalidSearchResult),
|
||||
HTTPReturnMessage: merr.ErrInvalidSearchResult.Error() + ", error: " + err.Error(),
|
||||
})
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{HTTPReturnCode: http.StatusOK, HTTPReturnData: outputData})
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -724,7 +724,7 @@ func genDynamicFields(fields []string, list []*schemapb.FieldData) []string {
|
|||
return dynamicFields
|
||||
}
|
||||
|
||||
func buildQueryResp(rowsNum int64, needFields []string, fieldDataList []*schemapb.FieldData, ids *schemapb.IDs, scores []float32) ([]map[string]interface{}, error) {
|
||||
func buildQueryResp(rowsNum int64, needFields []string, fieldDataList []*schemapb.FieldData, ids *schemapb.IDs, scores []float32, enableInt64 bool) ([]map[string]interface{}, error) {
|
||||
var queryResp []map[string]interface{}
|
||||
|
||||
columnNum := len(fieldDataList)
|
||||
|
@ -791,7 +791,11 @@ func buildQueryResp(rowsNum int64, needFields []string, fieldDataList []*schemap
|
|||
case schemapb.DataType_Int32:
|
||||
row[fieldDataList[j].FieldName] = fieldDataList[j].GetScalars().GetIntData().Data[i]
|
||||
case schemapb.DataType_Int64:
|
||||
row[fieldDataList[j].FieldName] = fieldDataList[j].GetScalars().GetLongData().Data[i]
|
||||
if enableInt64 {
|
||||
row[fieldDataList[j].FieldName] = fieldDataList[j].GetScalars().GetLongData().Data[i]
|
||||
} else {
|
||||
row[fieldDataList[j].FieldName] = strconv.FormatInt(fieldDataList[j].GetScalars().GetLongData().Data[i], 10)
|
||||
}
|
||||
case schemapb.DataType_Float:
|
||||
row[fieldDataList[j].FieldName] = fieldDataList[j].GetScalars().GetFloatData().Data[i]
|
||||
case schemapb.DataType_Double:
|
||||
|
@ -840,7 +844,11 @@ func buildQueryResp(rowsNum int64, needFields []string, fieldDataList []*schemap
|
|||
switch ids.IdField.(type) {
|
||||
case *schemapb.IDs_IntId:
|
||||
int64Pks := ids.GetIntId().GetData()
|
||||
row[DefaultPrimaryFieldName] = int64Pks[i]
|
||||
if enableInt64 {
|
||||
row[DefaultPrimaryFieldName] = int64Pks[i]
|
||||
} else {
|
||||
row[DefaultPrimaryFieldName] = strconv.FormatInt(int64Pks[i], 10)
|
||||
}
|
||||
case *schemapb.IDs_StrId:
|
||||
stringPks := ids.GetStrId().GetData()
|
||||
row[DefaultPrimaryFieldName] = stringPks[i]
|
||||
|
@ -856,3 +864,11 @@ func buildQueryResp(rowsNum int64, needFields []string, fieldDataList []*schemap
|
|||
|
||||
return queryResp, nil
|
||||
}
|
||||
|
||||
func formatInt64(intArray []int64) []string {
|
||||
stringArray := make([]string, 0)
|
||||
for _, i := range intArray {
|
||||
stringArray = append(stringArray, strconv.FormatInt(i, 10))
|
||||
}
|
||||
return stringArray
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ func generatePrimaryField(datatype schemapb.DataType) schemapb.FieldSchema {
|
|||
}
|
||||
}
|
||||
|
||||
func generateIds(num int) *schemapb.IDs {
|
||||
func generateIds(dataType schemapb.DataType, num int) *schemapb.IDs {
|
||||
var intArray []int64
|
||||
if num == 0 {
|
||||
intArray = []int64{}
|
||||
|
@ -40,13 +40,26 @@ func generateIds(num int) *schemapb.IDs {
|
|||
intArray = append(intArray, i)
|
||||
}
|
||||
}
|
||||
return &schemapb.IDs{
|
||||
IdField: &schemapb.IDs_IntId{
|
||||
IntId: &schemapb.LongArray{
|
||||
Data: intArray,
|
||||
switch dataType {
|
||||
case schemapb.DataType_Int64:
|
||||
return &schemapb.IDs{
|
||||
IdField: &schemapb.IDs_IntId{
|
||||
IntId: &schemapb.LongArray{
|
||||
Data: intArray,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
case schemapb.DataType_VarChar:
|
||||
stringArray := formatInt64(intArray)
|
||||
return &schemapb.IDs{
|
||||
IdField: &schemapb.IDs_StrId{
|
||||
StrId: &schemapb.StringArray{
|
||||
Data: stringArray,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateVectorFieldSchema(useBinary bool) schemapb.FieldSchema {
|
||||
|
@ -82,8 +95,8 @@ func generateVectorFieldSchema(useBinary bool) schemapb.FieldSchema {
|
|||
}
|
||||
}
|
||||
|
||||
func generateCollectionSchema(useBinary bool) *schemapb.CollectionSchema {
|
||||
primaryField := generatePrimaryField(schemapb.DataType_Int64)
|
||||
func generateCollectionSchema(datatype schemapb.DataType, useBinary bool) *schemapb.CollectionSchema {
|
||||
primaryField := generatePrimaryField(datatype)
|
||||
vectorField := generateVectorFieldSchema(useBinary)
|
||||
return &schemapb.CollectionSchema{
|
||||
Name: DefaultCollectionName,
|
||||
|
@ -196,7 +209,7 @@ func generateFieldData() []*schemapb.FieldData {
|
|||
return []*schemapb.FieldData{&fieldData1, &fieldData2, &fieldData3}
|
||||
}
|
||||
|
||||
func generateSearchResult() []map[string]interface{} {
|
||||
func generateSearchResult(dataType schemapb.DataType) []map[string]interface{} {
|
||||
row1 := map[string]interface{}{
|
||||
DefaultPrimaryFieldName: int64(1),
|
||||
FieldBookID: int64(1),
|
||||
|
@ -218,6 +231,11 @@ func generateSearchResult() []map[string]interface{} {
|
|||
FieldBookIntro: []float32{0.3, 0.33},
|
||||
HTTPReturnDistance: float32(0.09),
|
||||
}
|
||||
if dataType == schemapb.DataType_String {
|
||||
row1[DefaultPrimaryFieldName] = "1"
|
||||
row2[DefaultPrimaryFieldName] = "2"
|
||||
row3[DefaultPrimaryFieldName] = "3"
|
||||
}
|
||||
return []map[string]interface{}{row1, row2, row3}
|
||||
}
|
||||
|
||||
|
@ -246,9 +264,9 @@ func generateQueryResult64(withDistance bool) []map[string]interface{} {
|
|||
}
|
||||
|
||||
func TestPrintCollectionDetails(t *testing.T) {
|
||||
coll := generateCollectionSchema(false)
|
||||
coll := generateCollectionSchema(schemapb.DataType_Int64, false)
|
||||
indexes := generateIndexes()
|
||||
assert.Equal(t, printFields(coll.Fields), []gin.H{
|
||||
assert.Equal(t, []gin.H{
|
||||
{
|
||||
HTTPReturnFieldName: FieldBookID,
|
||||
HTTPReturnFieldType: "Int64",
|
||||
|
@ -270,23 +288,23 @@ func TestPrintCollectionDetails(t *testing.T) {
|
|||
HTTPReturnFieldAutoID: false,
|
||||
HTTPReturnDescription: "",
|
||||
},
|
||||
})
|
||||
assert.Equal(t, printIndexes(indexes), []gin.H{
|
||||
}, printFields(coll.Fields))
|
||||
assert.Equal(t, []gin.H{
|
||||
{
|
||||
HTTPReturnIndexName: DefaultIndexName,
|
||||
HTTPReturnIndexField: FieldBookIntro,
|
||||
HTTPReturnIndexMetricsType: DefaultMetricType,
|
||||
},
|
||||
})
|
||||
assert.Equal(t, getMetricType(indexes[0].Params), DefaultMetricType)
|
||||
assert.Equal(t, getMetricType(nil), DefaultMetricType)
|
||||
}, printIndexes(indexes))
|
||||
assert.Equal(t, DefaultMetricType, getMetricType(indexes[0].Params))
|
||||
assert.Equal(t, DefaultMetricType, getMetricType(nil))
|
||||
fields := []*schemapb.FieldSchema{}
|
||||
for _, field := range newCollectionSchema(coll).Fields {
|
||||
if field.DataType == schemapb.DataType_VarChar {
|
||||
fields = append(fields, field)
|
||||
}
|
||||
}
|
||||
assert.Equal(t, printFields(fields), []gin.H{
|
||||
assert.Equal(t, []gin.H{
|
||||
{
|
||||
HTTPReturnFieldName: "field-varchar",
|
||||
HTTPReturnFieldType: "VarChar(10)",
|
||||
|
@ -294,65 +312,65 @@ func TestPrintCollectionDetails(t *testing.T) {
|
|||
HTTPReturnFieldAutoID: false,
|
||||
HTTPReturnDescription: "",
|
||||
},
|
||||
})
|
||||
}, printFields(fields))
|
||||
}
|
||||
|
||||
func TestPrimaryField(t *testing.T) {
|
||||
coll := generateCollectionSchema(false)
|
||||
coll := generateCollectionSchema(schemapb.DataType_Int64, false)
|
||||
primaryField := generatePrimaryField(schemapb.DataType_Int64)
|
||||
field, ok := getPrimaryField(coll)
|
||||
assert.Equal(t, ok, true)
|
||||
assert.Equal(t, *field, primaryField)
|
||||
assert.Equal(t, true, ok)
|
||||
assert.Equal(t, primaryField, *field)
|
||||
|
||||
assert.Equal(t, joinArray([]int64{1, 2, 3}), "1,2,3")
|
||||
assert.Equal(t, joinArray([]string{"1", "2", "3"}), "1,2,3")
|
||||
assert.Equal(t, "1,2,3", joinArray([]int64{1, 2, 3}))
|
||||
assert.Equal(t, "1,2,3", joinArray([]string{"1", "2", "3"}))
|
||||
|
||||
jsonStr := "{\"id\": [1, 2, 3]}"
|
||||
idStr := gjson.Get(jsonStr, "id")
|
||||
rangeStr, err := convertRange(&primaryField, idStr)
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, rangeStr, "1,2,3")
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, "1,2,3", rangeStr)
|
||||
filter, err := checkGetPrimaryKey(coll, idStr)
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, filter, "book_id in [1,2,3]")
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, "book_id in [1,2,3]", filter)
|
||||
|
||||
primaryField = generatePrimaryField(schemapb.DataType_VarChar)
|
||||
jsonStr = "{\"id\": [\"1\", \"2\", \"3\"]}"
|
||||
idStr = gjson.Get(jsonStr, "id")
|
||||
rangeStr, err = convertRange(&primaryField, idStr)
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, rangeStr, "1,2,3")
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, "1,2,3", rangeStr)
|
||||
filter, err = checkGetPrimaryKey(coll, idStr)
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, filter, "book_id in [1,2,3]")
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, "book_id in [1,2,3]", filter)
|
||||
}
|
||||
|
||||
func TestInsertWithDynamicFields(t *testing.T) {
|
||||
body := "{\"data\": {\"id\": 0, \"book_id\": 1, \"book_intro\": [0.1, 0.2], \"word_count\": 2, \"classified\": false, \"databaseID\": null}}"
|
||||
req := InsertReq{}
|
||||
coll := generateCollectionSchema(false)
|
||||
coll := generateCollectionSchema(schemapb.DataType_Int64, false)
|
||||
var err error
|
||||
err, req.Data = checkAndSetData(body, &milvuspb.DescribeCollectionResponse{
|
||||
Status: &commonpb.Status{ErrorCode: commonpb.ErrorCode_Success},
|
||||
Schema: coll,
|
||||
})
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, req.Data[0]["id"], int64(0))
|
||||
assert.Equal(t, req.Data[0]["book_id"], int64(1))
|
||||
assert.Equal(t, req.Data[0]["word_count"], int64(2))
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, int64(0), req.Data[0]["id"])
|
||||
assert.Equal(t, int64(1), req.Data[0]["book_id"])
|
||||
assert.Equal(t, int64(2), req.Data[0]["word_count"])
|
||||
fieldsData, err := anyToColumns(req.Data, coll)
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, fieldsData[len(fieldsData)-1].IsDynamic, true)
|
||||
assert.Equal(t, fieldsData[len(fieldsData)-1].Type, schemapb.DataType_JSON)
|
||||
assert.Equal(t, string(fieldsData[len(fieldsData)-1].GetScalars().GetJsonData().GetData()[0]), "{\"classified\":false,\"id\":0}")
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, true, fieldsData[len(fieldsData)-1].IsDynamic)
|
||||
assert.Equal(t, schemapb.DataType_JSON, fieldsData[len(fieldsData)-1].Type)
|
||||
assert.Equal(t, "{\"classified\":false,\"id\":0}", string(fieldsData[len(fieldsData)-1].GetScalars().GetJsonData().GetData()[0]))
|
||||
}
|
||||
|
||||
func TestSerialize(t *testing.T) {
|
||||
parameters := []float32{0.11111, 0.22222}
|
||||
// assert.Equal(t, string(serialize(parameters)), "\ufffd\ufffd\ufffd=\ufffd\ufffdc\u003e")
|
||||
// assert.Equal(t, string(vector2PlaceholderGroupBytes(parameters)), "vector2PlaceholderGroupBytes") // todo
|
||||
assert.Equal(t, string(serialize(parameters)), "\xa4\x8d\xe3=\xa4\x8dc>")
|
||||
assert.Equal(t, string(vector2PlaceholderGroupBytes(parameters)), "\n\x10\n\x02$0\x10e\x1a\b\xa4\x8d\xe3=\xa4\x8dc>") // todo
|
||||
// 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
|
||||
}
|
||||
|
||||
func compareRow64(m1 map[string]interface{}, m2 map[string]interface{}) bool {
|
||||
|
@ -438,10 +456,10 @@ func compareRows(row1 []map[string]interface{}, row2 []map[string]interface{}, c
|
|||
|
||||
func TestBuildQueryResp(t *testing.T) {
|
||||
outputFields := []string{FieldBookID, FieldWordCount, "author", "date"}
|
||||
rows, err := buildQueryResp(int64(0), outputFields, generateFieldData(), generateIds(3), []float32{0.01, 0.04, 0.09}) // []*schemapb.FieldData{&fieldData1, &fieldData2, &fieldData3}
|
||||
assert.Equal(t, err, nil)
|
||||
exceptRows := generateSearchResult()
|
||||
assert.Equal(t, compareRows(rows, exceptRows, compareRow), true)
|
||||
rows, err := buildQueryResp(int64(0), outputFields, generateFieldData(), generateIds(schemapb.DataType_Int64, 3), []float32{0.01, 0.04, 0.09}, true) // []*schemapb.FieldData{&fieldData1, &fieldData2, &fieldData3}
|
||||
assert.Equal(t, nil, err)
|
||||
exceptRows := generateSearchResult(schemapb.DataType_Int64)
|
||||
assert.Equal(t, true, compareRows(rows, exceptRows, compareRow))
|
||||
}
|
||||
|
||||
func newCollectionSchema(coll *schemapb.CollectionSchema) *schemapb.CollectionSchema {
|
||||
|
@ -776,19 +794,19 @@ func newSearchResult(results []map[string]interface{}) []map[string]interface{}
|
|||
}
|
||||
|
||||
func TestAnyToColumn(t *testing.T) {
|
||||
data, err := anyToColumns(newSearchResult(generateSearchResult()), newCollectionSchema(generateCollectionSchema(false)))
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, len(data), 13)
|
||||
data, err := anyToColumns(newSearchResult(generateSearchResult(schemapb.DataType_Int64)), newCollectionSchema(generateCollectionSchema(schemapb.DataType_Int64, false)))
|
||||
assert.Equal(t, nil, err)
|
||||
assert.Equal(t, 13, len(data))
|
||||
}
|
||||
|
||||
func TestBuildQueryResps(t *testing.T) {
|
||||
outputFields := []string{"XXX", "YYY"}
|
||||
outputFieldsList := [][]string{outputFields, {"$meta"}, {"$meta", FieldBookID, FieldBookIntro, "YYY"}}
|
||||
for _, theOutputFields := range outputFieldsList {
|
||||
rows, err := buildQueryResp(int64(0), theOutputFields, newFieldData(generateFieldData(), schemapb.DataType_None), generateIds(3), []float32{0.01, 0.04, 0.09})
|
||||
assert.Equal(t, err, nil)
|
||||
exceptRows := newSearchResult(generateSearchResult())
|
||||
assert.Equal(t, compareRows(rows, exceptRows, compareRow), true)
|
||||
rows, err := buildQueryResp(int64(0), theOutputFields, newFieldData(generateFieldData(), schemapb.DataType_None), generateIds(schemapb.DataType_Int64, 3), []float32{0.01, 0.04, 0.09}, true)
|
||||
assert.Equal(t, nil, err)
|
||||
exceptRows := newSearchResult(generateSearchResult(schemapb.DataType_Int64))
|
||||
assert.Equal(t, true, compareRows(rows, exceptRows, compareRow))
|
||||
}
|
||||
|
||||
dataTypes := []schemapb.DataType{
|
||||
|
@ -799,18 +817,29 @@ func TestBuildQueryResps(t *testing.T) {
|
|||
schemapb.DataType_JSON, schemapb.DataType_Array,
|
||||
}
|
||||
for _, dateType := range dataTypes {
|
||||
_, err := buildQueryResp(int64(0), outputFields, newFieldData([]*schemapb.FieldData{}, dateType), generateIds(3), []float32{0.01, 0.04, 0.09})
|
||||
assert.Equal(t, err, nil)
|
||||
_, err := buildQueryResp(int64(0), outputFields, newFieldData([]*schemapb.FieldData{}, dateType), generateIds(schemapb.DataType_Int64, 3), []float32{0.01, 0.04, 0.09}, true)
|
||||
assert.Equal(t, nil, err)
|
||||
}
|
||||
|
||||
_, err := buildQueryResp(int64(0), outputFields, newFieldData([]*schemapb.FieldData{}, 1000), generateIds(3), []float32{0.01, 0.04, 0.09})
|
||||
assert.Equal(t, err.Error(), "the type(1000) of field(wrong-field-type) is not supported, use other sdk please")
|
||||
_, err := buildQueryResp(int64(0), outputFields, newFieldData([]*schemapb.FieldData{}, 1000), generateIds(schemapb.DataType_Int64, 3), []float32{0.01, 0.04, 0.09}, true)
|
||||
assert.Equal(t, "the type(1000) of field(wrong-field-type) is not supported, use other sdk please", err.Error())
|
||||
|
||||
res, err := buildQueryResp(int64(0), outputFields, []*schemapb.FieldData{}, generateIds(3), []float32{0.01, 0.04, 0.09})
|
||||
assert.Equal(t, len(res), 3)
|
||||
assert.Equal(t, err, nil)
|
||||
res, err := buildQueryResp(int64(0), outputFields, []*schemapb.FieldData{}, generateIds(schemapb.DataType_Int64, 3), []float32{0.01, 0.04, 0.09}, true)
|
||||
assert.Equal(t, 3, len(res))
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
res, err = buildQueryResp(int64(0), outputFields, []*schemapb.FieldData{}, generateIds(schemapb.DataType_Int64, 3), []float32{0.01, 0.04, 0.09}, false)
|
||||
assert.Equal(t, 3, len(res))
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
res, err = buildQueryResp(int64(0), outputFields, []*schemapb.FieldData{}, generateIds(schemapb.DataType_VarChar, 3), []float32{0.01, 0.04, 0.09}, true)
|
||||
assert.Equal(t, 3, len(res))
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
_, err = buildQueryResp(int64(0), outputFields, generateFieldData(), generateIds(schemapb.DataType_Int64, 3), []float32{0.01, 0.04, 0.09}, false)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
// len(rows) != len(scores), didn't show distance
|
||||
_, err = buildQueryResp(int64(0), outputFields, newFieldData(generateFieldData(), schemapb.DataType_None), generateIds(3), []float32{0.01, 0.04})
|
||||
assert.Equal(t, err, nil)
|
||||
_, err = buildQueryResp(int64(0), outputFields, newFieldData(generateFieldData(), schemapb.DataType_None), generateIds(schemapb.DataType_Int64, 3), []float32{0.01, 0.04}, true)
|
||||
assert.Equal(t, nil, err)
|
||||
}
|
||||
|
|
|
@ -169,6 +169,15 @@ func (s *Server) startHTTPServer(errChan chan error) {
|
|||
defer s.wg.Done()
|
||||
ginHandler := gin.Default()
|
||||
ginHandler.Use(func(c *gin.Context) {
|
||||
_, err := strconv.ParseBool(c.Request.Header.Get(httpserver.HTTPHeaderAllowInt64))
|
||||
if err != nil {
|
||||
httpParams := ¶mtable.Get().HTTPCfg
|
||||
if httpParams.AcceptTypeAllowInt64.GetAsBool() {
|
||||
c.Request.Header.Set(httpserver.HTTPHeaderAllowInt64, "true")
|
||||
} else {
|
||||
c.Request.Header.Set(httpserver.HTTPHeaderAllowInt64, "false")
|
||||
}
|
||||
}
|
||||
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package paramtable
|
||||
|
||||
type httpConfig struct {
|
||||
Enabled ParamItem `refreshable:"false"`
|
||||
DebugMode ParamItem `refreshable:"false"`
|
||||
Port ParamItem `refreshable:"false"`
|
||||
Enabled ParamItem `refreshable:"false"`
|
||||
DebugMode ParamItem `refreshable:"false"`
|
||||
Port ParamItem `refreshable:"false"`
|
||||
AcceptTypeAllowInt64 ParamItem `refreshable:"false"`
|
||||
}
|
||||
|
||||
func (p *httpConfig) init(base *BaseTable) {
|
||||
|
@ -33,4 +34,14 @@ func (p *httpConfig) init(base *BaseTable) {
|
|||
Export: true,
|
||||
}
|
||||
p.Port.Init(base.mgr)
|
||||
|
||||
p.AcceptTypeAllowInt64 = ParamItem{
|
||||
Key: "proxy.http.acceptTypeAllowInt64",
|
||||
DefaultValue: "false",
|
||||
Version: "2.3.2",
|
||||
Doc: "high-level restful api, whether http client can deal with int64",
|
||||
PanicIfEmpty: false,
|
||||
Export: true,
|
||||
}
|
||||
p.AcceptTypeAllowInt64.Init(base.mgr)
|
||||
}
|
||||
|
|
|
@ -13,4 +13,5 @@ func TestHTTPConfig_Init(t *testing.T) {
|
|||
assert.Equal(t, cfg.Enabled.GetAsBool(), true)
|
||||
assert.Equal(t, cfg.DebugMode.GetAsBool(), false)
|
||||
assert.Equal(t, cfg.Port.GetValue(), "")
|
||||
assert.Equal(t, cfg.AcceptTypeAllowInt64.GetValue(), "false")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue