From 77fc6eec6b9bff91bd21ca8edbc15fd3e2b5e6c3 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Fri, 6 Feb 2026 12:08:10 +0800 Subject: [PATCH] bugfix --- README.md | 129 +++++++++++++++++++++++++++++++++++++++++++++++ conf/config.json | 60 ++++++++++++++++++++++ db/README.md | 0 vdb/milvus.py | 33 ++++++++---- 4 files changed, 211 insertions(+), 11 deletions(-) create mode 100644 conf/config.json create mode 100644 db/README.md diff --git a/README.md b/README.md index b973c64..f8f0b4e 100644 --- a/README.md +++ b/README.md @@ -51,3 +51,132 @@ } ] ``` + +## API +对外提供http的接口,安全要求会提供客户端ip过滤 + +### 创建集合 + +path:/v1/createcollection +method:POST +headers:{ + "Content-Type": "application/json" +} +data:{ + colname: 集合名字,必须提供 + fields: 集合字段集,请参照字段类型提供 + description:可选, 集合描述 +} + +成功返回 +{ + "status":"SUCCEEDED" +} + +失败返回 +{ + "status":"FAILED", + "error": 错误信息 +} + +### 删除集合 + +path:/v1/dropcollection +method:POST +headers:{ + "Content-Type": "application/json" +} +data:{ + colname: 集合名字,必须提供 +} + +成功返回 +{ + "status":"SUCCEEDED" +} + +失败返回 +{ + "status":"FAILED", + "error": 错误信息 +} + +### 向集合插入一到多条记录 + +path:/v1/upsert +method:POST +headers:{ + "Content-Type": "application/json" +} +data:{ + colname: 集合名字,必须提供 + data: 数据字典或数据字典数组 +} + +成功返回 +{ + "status":"SUCCEEDED" +} + +失败返回 +{ + "status":"FAILED", + "error": 错误信息 +} + +### 删除集合一到多条记录 + +path:/v1/delete +method:POST +headers:{ + "Content-Type": "application/json" +} +data:{ + colname: 集合名字,必须提供 + pks: 主键或主键数组 + description:可选, 集合描述 +} + +成功返回 +{ + "status":"SUCCEEDED" +} + +失败返回 +{ + "status":"FAILED", + "error": 错误信息 +} + +### 查询集合数据 + +path:/v1/createcollection +method:POST +headers:{ + "Content-Type": "application/json" +} +data:{ + colname: 集合名字,必须提供 + fields: 集合字段集,请参照字段类型提供 + description:可选, 集合描述 +} + +成功返回 +{ + "status":"SUCCEEDED" + "data": 返回数据 +} + +失败返回 +{ + "status":"FAILED", + "error": 错误信息 +} + +返回数据有如下结构 +{ + "total": -1, # 不知道总共多少条符合条件的数据 + "page": 当前页(起始1) + "pagerows": 每页记录数 + "rows": 记录数据 +} diff --git a/conf/config.json b/conf/config.json new file mode 100644 index 0000000..875e873 --- /dev/null +++ b/conf/config.json @@ -0,0 +1,60 @@ +{ + "vdb_type": "milvus", + "filesroot": "$[workdir]$/files", + "milvus_db": "$[workdir]$/db/milvus.db", + "logger": { + "name": "vdb", + "levelname": "info", + "logfile": "$[workdir]$/logs/vdb.log" + }, + "website": { + "paths": [ + ["$[workdir]$/wwwroot", ""] + ], + "client_max_size": 10000, + "host": "0.0.0.0", + "port": 8886, + "coding": "utf-8", + "indexes": [ + "index.html", + "index.dspy", + "index.ui" + ], + "startswiths": [ + { + "leading": "/idfile", + "registerfunction": "idfile" + }, + { + "leading": "/v1/createcollection", + "registerfunction": "create_collection" + }, + { + "leading": "/v1/dropcollection", + "registerfunction": "drop_collection" + }, + { + "leading": "/v1/iupsert", + "registerfunction": "upsert" + }, + { + "leading": "/v1/delete", + "registerfunction": "delete" + }, + { + "leading": "/v1/query", + "registerfunction": "query" + }, + { + "leading": "/docs", + "registerfunction": "docs" + } + ], + "processors": [ + [".tmpl", "tmpl"], + [".app", "app"], + [".ui", "bui"], + [".dspy", "dspy"], + [".md", "md"] + ], + diff --git a/db/README.md b/db/README.md new file mode 100644 index 0000000..e69de29 diff --git a/vdb/milvus.py b/vdb/milvus.py index 66501c6..028a32f 100644 --- a/vdb/milvus.py +++ b/vdb/milvus.py @@ -141,14 +141,14 @@ class MilvusManager(BaseVDB): return [columnar_data[f] for f in required_fields] - def upsert(self, collection_name, data_dicts, partition_name=None): + def upsert(self, collection_name, data_dicts): """通用 Upsert:支持字典列表输入,自动识别主键更新""" pks = [item['id'] for item in data_dicts] self.delete(collection_name, pks) col = Collection(collection_name, using=self.alias) if self.partitionize is None: formatted_data = self._validate_and_format(col, data_dicts) - res = col.upsert(formatted_data, partition_name=partition_name) + res = col.upsert(formatted_data) col.flush() # 内网环境强制落盘以防数据丢失 return res grouped_data = {} @@ -201,14 +201,25 @@ class MilvusManager(BaseVDB): vec_field = next(f.name for f in col.schema.fields if f.dtype == DataType.FLOAT_VECTOR) search_params = {"metric_type": "L2", "params": {"ef": 64}, "offset": offset} - return col.search( - data=[vector], - anns_field=vec_field, - param=search_params, - limit=limit, - expr=expr, - output_fields=output_fields - ) + return { + "total": -1, + "page": page, + "pagerows": pagerows, + "rows": col.search( + data=[vector], + anns_field=vec_field, + param=search_params, + limit=limit, + offset=offset, + expr=expr, + output_fields=output_fields + ) + } else: # 纯标量查询 - return col.query(expr=expr, limit=limit, offset=offset, output_fields=output_fields) + return { + "total": -1, + "page": page, + "pagerows": pagerows, + "rows": col.query(expr=expr, limit=limit, offset=offset, output_fields=output_fields) + }