点操作 API¶
本文件面向“点操作”API,系统性地记录与实现相关的 HTTP 端点:PUT /collections/{name}/points(Upsert 点)、POST /collections/{name}/points/search(搜索)、POST /collections/{name}/points/delete(删除)。文档涵盖:
- 端点请求/响应模式与字段定义
- PointStruct 结构、向量数据格式、过滤条件语法
- Upsert 批量插入、更新与覆盖机制
- 搜索查询参数配置(向量、过滤器、限制数量)
- 删除操作的多种方式(按 ID 与按过滤条件)
- 完整的 JSON 示例与错误处理说明
项目结构¶
该服务采用分层设计:
- API 层:负责路由与 HTTP 协议编解码
- 核心层:Collection、Index、Storage 等业务逻辑
- 存储层:基于 bbolt 的本地持久化,配合 Protobuf 序列化
graph TB
subgraph "API 层"
S["Server
路由与HTTP处理"]
end
subgraph "核心层"
C["Collection
集合管理"]
I["VectorIndex
索引接口"]
F["Flat/HNSW 索引"]
M["Models
PointStruct/Filter/ScoredPoint"]
D["Distance
Cosine/Euclid/Dot"]
end
subgraph "存储层"
ST["Storage
bbolt + Protobuf"]
end
S --> C
C --> I
I --> F
C --> ST
M --> D
核心组件¶
- Server:HTTP 路由与请求处理,暴露点操作端点
- Collection:集合抽象,封装 Upsert/Search/Delete 业务
- VectorIndex 接口:统一的索引能力(Upsert/Search/Delete/Count/Filter)
- Storage:本地持久化,支持 bbolt 与 Protobuf 序列化
- Models:数据模型(PointStruct、Filter、ScoredPoint)与匹配算法
- Distance:距离度量(Cosine/Euclid/Dot)
架构总览¶
点操作 API 的调用链路如下:
sequenceDiagram
participant Client as "客户端"
participant API as "Server.handleUpsert/Search/Delete"
participant Col as "Collection"
participant Idx as "VectorIndex"
participant St as "Storage"
Client->>API : "PUT /collections/{name}/points"
请求体 : {points : [PointStruct]}
API->>Col : "Upsert(points)"
Col->>St : "UpsertPoints(collection, points)"
Col->>Idx : "Upsert(points)"
Idx-->>Col : "OK"
St-->>Col : "OK"
Col-->>API : "OK"
API-->>Client : "{status : 'ok', result : {operation : 'completed'}}"
Client->>API : "POST /collections/{name}/points/search"
请求体 : {vector : [], filter?, limit : int}
API->>Col : "Search(vector, filter, limit)"
Col->>Idx : "Search(vector, filter, limit)"
Idx-->>Col : "[]ScoredPoint"
Col-->>API : "[]ScoredPoint"
API-->>Client : "{status : 'ok', result : []}"
Client->>API : "POST /collections/{name}/points/delete"
请求体 : {points : [], filter?}
API->>Col : "Delete(points, filter)"
Col->>St : "DeletePoints(collection, ids)"
Col->>Idx : "Delete(id) for each id"
Idx-->>Col : "OK"
St-->>Col : "OK"
Col-->>API : "deleted : int"
API-->>Client : "{status : 'ok', result : {operation : 'completed', deleted : int}}"
详细组件分析¶
点结构与过滤器模型¶
- PointStruct:包含唯一标识、版本号、向量、可选负载(用于过滤)
- ScoredPoint:搜索结果,包含相似度分数与点信息
- Filter:支持 must/must_not 条件,条件类型包括 exact、range、prefix、contains、regex
- Distance:支持 Cosine、Euclid、Dot 三种度量
classDiagram
class PointStruct {
+string id
+uint64 version
+[]float32 vector
+map[string]interface{
} payload
}
class ScoredPoint {
+string id
+uint64 version
+float32 score
+map[string]interface{
} payload
}
class Filter {
+[]Condition must
+[]Condition must_not
}
class Condition {
+string key
+string type
+MatchValue match
+RangeValue range
}
class MatchValue {
+interface{
} value
}
class RangeValue {
+interface{
} gt
+interface{} gte
+interface{} lt
+interface{} lte
}
class Distance {
<>
+Cosine
+Euclid
+Dot
}
ScoredPoint --> PointStruct : "包含"
Filter --> Condition : "组合"
Condition --> MatchValue : "匹配值"
Condition --> RangeValue : "范围值"
Collection ..> Distance : "使用"
Upsert 点(PUT /collections/{name}/points)¶
- 功能:批量插入或更新点;若集合不存在返回 404;请求体必须为合法 JSON 返回 400;内部错误返回 500
- 请求体字段
- points:数组,元素为 PointStruct
- 响应体字段
- status:字符串,固定为 "ok"
- result.operation:字符串,固定为 "completed"
- 处理流程
- 解析 JSON -> 校验集合存在 -> 调用 Collection.Upsert -> 成功返回 200 OK
sequenceDiagram
participant Client as "客户端"
participant API as "Server.handleUpsert"
participant Col as "Collection"
participant St as "Storage"
participant Idx as "VectorIndex"
Client->>API : "PUT /collections/{name}/points"
{points : [PointStruct]}
API->>API : "解析JSON"
API->>Col : "Upsert(points)"
Col->>St : "UpsertPoints(name, points)"
Col->>Idx : "Upsert(points)"
Idx-->>Col : "OK"
St-->>Col : "OK"
Col-->>API : "OK"
API-->>Client : "{status : 'ok', result : {operation : 'completed'}}"
搜索(POST /collections/{name}/points/search)¶
- 功能:根据向量进行相似度检索,支持可选过滤器与限制数量
- 请求体字段
- vector:数组,浮点数,维度需与集合一致
- filter:可选,Filter 对象
- limit:整数,返回前 K 个结果,默认 10
- 响应体字段
- status:字符串,固定为 "ok"
- result:数组,元素为 ScoredPoint
- 处理流程
- 解析 JSON -> 校验集合存在 -> 校验向量维度 -> 调用 Collection.Search -> 返回 200 OK
sequenceDiagram
participant Client as "客户端"
participant API as "Server.handleSearch"
participant Col as "Collection"
participant Idx as "VectorIndex"
Client->>API : "POST /collections/{name}/points/search"
{vector : [], filter?, limit : int}
API->>API : "解析JSON"
API->>Col : "Search(vector, filter, limit)"
Col->>Idx : "Search(vector, filter, limit)"
Idx-->>Col : "[]ScoredPoint"
Col-->>API : "[]ScoredPoint"
API-->>Client : "{status : 'ok', result : []}"
删除(POST /collections/{name}/points/delete)¶
- 功能:支持按 ID 删除或按过滤条件删除;二者至少提供其一
- 请求体字段
- points:可选,字符串数组,指定要删除的点 ID
- filter:可选,Filter 对象,匹配要删除的点
- 响应体字段
- status:字符串,固定为 "ok"
- result.operation:字符串,固定为 "completed"
- result.deleted:整数,实际删除的点数量
- 处理流程
- 解析 JSON -> 校验集合存在 -> 计算目标 ID 列表(ID 或通过过滤器推导)-> 先删除存储再删除索引 -> 返回 200 OK
sequenceDiagram
participant Client as "客户端"
participant API as "Server.handleDelete"
participant Col as "Collection"
participant St as "Storage"
participant Idx as "VectorIndex"
Client->>API : "POST /collections/{name}/points/delete"
{points : [], filter?}
API->>API : "解析JSON"
API->>Col : "Delete(points, filter)"
alt 提供 points
Col->>St : "DeletePoints(name, ids)"
Col->>Idx : "Delete(id) for each id"
else 提供 filter
Col->>Idx : "GetIDsByFilter(filter)"
Col->>St : "DeletePoints(name, ids)"
Col->>Idx : "Delete(id) for each id"
end
Idx-->>Col : "OK"
St-->>Col : "OK"
Col-->>API : "deleted : int"
API-->>Client : "{status : 'ok', result : {operation : 'completed', deleted : int}}"
过滤器语法与匹配规则¶
- Filter
- must:所有条件都必须满足
- must_not:任何条件都不能满足
- Condition
- key:负载中的键名
- type:匹配类型
- exact:精确相等
- range:数值范围比较(gt/gte/lt/lte)
- prefix:字符串前缀匹配
- contains:数组/字符串包含
- regex:正则表达式匹配
- match:匹配值
- range:范围值对象
- 匹配算法
- 数值范围:支持 int 与 float64
- 字符串前缀:长度检查
- 数组/字符串包含:逐项比较
- 正则:编译并匹配
flowchart TD
Start(["进入过滤匹配"]) --> Nil{"Filter为空?"}
Nil --> |是| TrueAll["返回true全部匹配"]
Nil --> |否| Must["遍历must条件"]
Must --> MustAll{"全部满足?"}
MustAll --> |否| FalseAll["返回false"]
MustAll --> |是| MustNot["遍历must_not条件"]
MustNot --> None{"任一满足?"}
None --> |是| FalseAll
None --> |否| TrueAll
向量数据格式与度量¶
- 向量:[]float32,维度需与集合一致
- 度量:
- Cosine:[-1, 1],值越大越相似
- Euclid:[0, +∞),值越小越相似
- Dot:(-∞, +∞),值越大越相似
- 默认度量为 Cosine
端点与错误码¶
- PUT /collections/{name}/points
- 200:成功
- 400:无效 JSON
- 404:集合不存在
- 500:内部错误
- POST /collections/{name}/points/search
- 200:成功
- 400:无效 JSON
- 404:集合不存在
- 500:内部错误
- POST /collections/{name}/points/delete
- 200:成功
- 400:无效 JSON
- 404:集合不存在
- 500:内部错误
依赖分析¶
- API 层依赖核心层的 Collection 与 Index 接口
- Collection 依赖 VectorIndex 与 Storage
- Storage 依赖 bbolt 与 Protobuf
- Models 与 Distance 为纯数据与计算层
graph LR
API["api/server.go"] --> COL["core/collection.go"]
COL --> IDX["core/index.go"]
COL --> ST["core/storage.go"]
COL --> MOD["core/models.go"]
MOD --> MATH["core/math.go"]
ST --> PB["core/proto/point.proto"]
性能考虑¶
- 索引选择:Flat(内存暴力)与 HNSW(图近似)可切换,HNSW 在大规模场景下具备更优的查询延迟
- 持久化顺序:先写存储再更新索引,保证一致性与可恢复性
- 向量量化:可启用 SQ8 量化以降低磁盘占用与加载成本
- 查询默认限制:未显式设置 limit 时默认返回前 10 条结果
故障排除指南¶
- 集合不存在
- 现象:404 Not Found
- 排查:确认集合名称正确且已创建
- JSON 解析失败
- 现象:400 Bad Request
- 排查:检查请求体是否为合法 JSON
- 向量维度不匹配
- 现象:Search 时返回 500 内部错误
- 排查:确保 vector 维度与集合一致
- 删除参数缺失
- 现象:Delete 返回 500 内部错误(提示必须提供 points 或 filter)
- 排查:至少提供 points 或 filter 其中之一
结论¶
点操作 API 提供了与 Qdrant 兼容的 REST 接口,覆盖 Upsert、Search、Delete 三大核心能力。通过 Collection 抽象与 VectorIndex 接口,系统在一致性、可扩展性与性能之间取得平衡。建议在生产环境结合 HNSW 索引与向量量化以获得最佳吞吐与延迟表现。
附录¶
端点定义与示例¶
- Upsert(PUT /collections/{name}/points)
- 请求体
- points:数组,元素为 PointStruct
- id:字符串,唯一标识
- version:整数,版本号(自动赋值)
- vector:数组,浮点数,维度需与集合一致
- payload:可选,键值对,用于过滤
-
响应体
- status:字符串,固定为 "ok"
- result.operation:字符串,固定为 "completed"
-
搜索(POST /collections/{name}/points/search)
- 请求体
- vector:数组,浮点数,维度需与集合一致
- filter:可选,Filter 对象
- must:[]Condition
- must_not:[]Condition
- limit:整数,返回前 K 个结果,默认 10
-
响应体
- status:字符串,固定为 "ok"
- result:数组,元素为 ScoredPoint
- id:字符串
- version:整数
- score:浮点数
- payload:可选
-
删除(POST /collections/{name}/points/delete)
- 请求体
- points:可选,字符串数组,指定要删除的点 ID
- filter:可选,Filter 对象,匹配要删除的点
- 响应体
- status:字符串,固定为 "ok"
- result.operation:字符串,固定为 "completed"
- result.deleted:整数,实际删除的点数量
过滤器语法参考¶
- exact:精确匹配
- range:gt/gte/lt/lte 数值范围
- prefix:字符串前缀
- contains:数组/字符串包含
- regex:正则表达式
示例请求/响应(路径引用)¶
- Upsert 请求体示例
- api/server_test.go:344-349
- 搜索请求体示例
- api/server_test.go:386-389
- 删除请求体示例(按 ID)
- api/server_test.go:435-437
- 删除请求体示例(按过滤条件)
- api/server_test.go:451-457