聚合统计用于对索引中的数据做统计计算,适合在不拉取明细数据的情况下快速了解数据规模、字段分布、数值汇总结果,或对指定向量做加权求和。
当前 agg 接口支持三类聚合:
| 聚合类型 | 支持算子 | 功能说明 | 适用场景 |
|---|---|---|---|
| 标量计数聚合 | count | 统计命中数据量。传入 group_by 时按字段分桶;不传时统计全局数量。 | 用以查看索引数据总量,或查看城市、品类、状态等低基数字段的数据分布。 |
| 标量计算聚合 | sum、avg、min、max | 对指定数值字段做求和、平均值、最小值或最大值计算。也可以配合 group_by 按字段分桶计算。 | 统计价格、评分、耗时、库存等数值指标。 |
| 向量计算聚合 | vector_weighted_sum | 对一组主键对应的向量按权重求和。 | 用于向量池化、用户兴趣向量合成、查询向量融合等场景。 |
其中,标量类聚合支持通过 filter 缩小统计范围,对标 SQL 中的 WHERE;也支持通过 group_by 按字段分桶聚合,对标 SQL 中的 GROUP BY。分桶聚合适合做数据分布概览,不适合用来导出高基数字段的完整明细。
对应的 V1 接口为:https://www.volcengine.com/docs/84313/1399339
| 功能 | V2 接口 | V1 接口 |
|---|---|---|
| 子索引 | 性能和易用性更强的分片能力研发中,敬请期待。 | 通过 partition 参数指定。 |
请求向量数据库 VikingDB 的 OpenAPI 接口时,可以使用 API Key(推荐)或者 AK、SK 构造签名进行鉴权。请参见数据面 API 调用流程,复制调用示例并填入必要信息。
| 配置项 | 说明 |
|---|---|
| URI | /api/vikingdb/data/agg |
| 方法 | POST |
| 请求头 | Content-Type: application/json |
| 请求头 | Authorization: *** |
| 参数名 | 类型 | 必选 | 说明 |
|---|---|---|---|
resource_id | string | 与 collection_name 二选一 | 资源 ID。 |
collection_name | string | 与 resource_id 二选一 | Collection 名称。 |
index_name | string | 是 | Index 名称。 |
op | string | 是 | 聚合算子。支持 count、sum、avg、min、max、vector_weighted_sum。 |
filter | map | 否 | 过滤条件,格式与检索接口一致。仅标量聚合支持;不传时表示在当前索引内聚合。 |
group_by | string | 否 | 分桶字段。仅标量聚合支持;不传时表示全局聚合。 |
calc_value_on | string | op参数设置sum、avg、min、max时必填 | 标量计算字段。仅 sum、avg、min、max 使用。 |
order | string | 否 | 分桶结果排序方向。取值为 desc 或 asc,默认 desc。仅分桶标量聚合使用。 |
ids | array | op参数设置vector_weighted_sum时必填 | 参与向量加权求和的主键列表,格式与 Collection 主键类型一致。单次最多 2000 个。 |
weights | array<float> | op参数设置vector_weighted_sum时必填 | 与 ids 一一对应的权重列表,长度必须与 ids 相同,权重必须是有限数值。 |
op | 必填参数 | 可选参数 | 说明 |
|---|---|---|---|
count | 无 | group_by、filter、order | 不传 group_by 时统计索引数据总量;传入 group_by 时按字段分桶计数。 |
sum | calc_value_on | group_by、filter、order | 对指定数值字段求和。 |
avg | calc_value_on | group_by、filter、order | 对指定数值字段求平均值。 |
min | calc_value_on | group_by、filter、order | 返回指定数值字段的最小值。 |
max | calc_value_on | group_by、filter、order | 返回指定数值字段的最大值。 |
vector_weighted_sum | ids、weights | 无 | 对指定主键对应的向量做加权求和。 |
| 参数 | 支持类型 | 索引要求 |
|---|---|---|
group_by | string、int64、bool | 字段需要已建立枚举索引。 |
calc_value_on | int64、float32 | 字段需要已建立范围索引。 |
使用 count 时,索引中需要至少存在一个可用于聚合的标量索引字段。使用 vector_weighted_sum 时,Collection 需要包含向量字段,或在创建 Collection 时配置了向量化参数(Vectorize)。
不传 group_by 时,接口执行全局聚合,响应中的 group_by 为 __NONE__,聚合结果使用 __TOTAL__ 作为结果键。
传入 group_by 时,接口执行分桶聚合。每个桶的 key 为对应字段值,value 为该桶的聚合结果。
order 只对分桶标量聚合生效:
| 取值 | 说明 |
|---|---|
desc | 按聚合结果从大到小排序,默认值。 |
asc | 按聚合结果从小到大排序。 |
分桶聚合最多返回 10000 个桶。聚合统计适合做分布概览,不适合用来导出高基数字段的完整分桶明细。如果一个字段的不同取值非常多,建议先用更严格的 filter 缩小范围,或在业务侧选择更粗粒度的分桶字段。
公共响应体参数见数据面 API 调用流程。
| 参数名 | 类型 | 说明 |
|---|---|---|
op | string | 本次执行的聚合算子。 |
group_by | string | 分桶字段。全局聚合时返回 __NONE__。 |
calc_value_on | string | 标量计算字段。仅 sum、avg、min、max 返回。 |
agg | map | 标量聚合结果。count、sum、avg、min、max 返回。 |
vector_weighted_sum | map | 向量加权求和结果。仅 vector_weighted_sum 返回。 |
agg 的 value 类型与算子和字段类型有关:
| 算子 | 结果类型 |
|---|---|
count | 整数。 |
sum | calc_value_on 为 int64 时返回整数;为 float32 时返回浮点数。 |
avg | 浮点数。 |
min | calc_value_on 为 int64 时返回整数;为 float32 时返回浮点数。 |
max | calc_value_on 为 int64 时返回整数;为 float32 时返回浮点数。 |
vector_weighted_sum 包含以下字段:
| 参数名 | 类型 | 说明 |
|---|---|---|
vector | array<float> | 加权求和后的向量。 |
found_ids | array | 实际命中并参与计算的主键列表,返回顺序与请求中的 ids 顺序一致。 |
found_count | int | 实际命中并参与计算的主键数量。 |
weight_sum | float | 实际参与计算的权重和。未命中的主键不计入该值。 |
以下示例使用同一个索引:
collection_name: test_collindex_name: idx_1category,类型为 string,已建立枚举索引。price,类型为 float32,已建立范围索引。4。示例数据的统计结果如下:
123 条数据。category = book 的数据有 80 条,price 求和为 234567.0。category = toy 的数据有 43 条,price 求和为 222222.0。price 求和为 456789.0,平均值为 3713.731707317073。price 最小值为 12.5,最大值为 9999.0。请求参数:
req_path = "/api/vikingdb/data/agg" req_body = { "collection_name": "test_coll", "index_name": "idx_1", "op": "count", }
响应参数:
{ "code": "Success", "message": "The API call was executed successfully.", "request_id": "02175438839168500000000000000000000ffff0a003ee4fc3499", "result": { "op": "count", "group_by": "__NONE__", "agg": { "__TOTAL__": 123 } } }
请求参数:
req_path = "/api/vikingdb/data/agg" req_body = { "collection_name": "test_coll", "index_name": "idx_1", "op": "count", "group_by": "category", "order": "desc", }
响应参数:
{ "code": "Success", "message": "The API call was executed successfully.", "request_id": "02175438839168500000000000000000000ffff0a003ee4fc3499", "result": { "op": "count", "group_by": "category", "agg": { "book": 80, "toy": 43 } } }
请求参数:
req_path = "/api/vikingdb/data/agg" req_body = { "collection_name": "test_coll", "index_name": "idx_1", "op": "avg", "calc_value_on": "price", }
响应参数:
{ "code": "Success", "message": "The API call was executed successfully.", "request_id": "02175438839168500000000000000000000ffff0a003ee4fc3499", "result": { "op": "avg", "group_by": "__NONE__", "calc_value_on": "price", "agg": { "__TOTAL__": 3713.731707317073 } } }
请求参数:
req_path = "/api/vikingdb/data/agg" req_body = { "collection_name": "test_coll", "index_name": "idx_1", "op": "sum", "calc_value_on": "price", "group_by": "category", "order": "desc", }
响应参数:
{ "code": "Success", "message": "The API call was executed successfully.", "request_id": "02175438839168500000000000000000000ffff0a003ee4fc3499", "result": { "op": "sum", "group_by": "category", "calc_value_on": "price", "agg": { "book": 234567.0, "toy": 222222.0 } } }
请求参数:
req_path = "/api/vikingdb/data/agg" req_body = { "collection_name": "test_coll", "index_name": "idx_1", "op": "min", "calc_value_on": "price", }
响应参数:
{ "code": "Success", "message": "The API call was executed successfully.", "request_id": "02175438839168500000000000000000000ffff0a003ee4fc3499", "result": { "op": "min", "group_by": "__NONE__", "calc_value_on": "price", "agg": { "__TOTAL__": 12.5 } } }
请求参数:
req_path = "/api/vikingdb/data/agg" req_body = { "collection_name": "test_coll", "index_name": "idx_1", "op": "max", "calc_value_on": "price", }
响应参数:
{ "code": "Success", "message": "The API call was executed successfully.", "request_id": "02175438839168500000000000000000000ffff0a003ee4fc3499", "result": { "op": "max", "group_by": "__NONE__", "calc_value_on": "price", "agg": { "__TOTAL__": 9999.0 } } }
请求参数:
req_path = "/api/vikingdb/data/agg" req_body = { "collection_name": "test_coll", "index_name": "idx_1", "op": "vector_weighted_sum", "ids": [101, 102, 103], "weights": [0.2, 0.3, 0.5], }
假设这 3 个主键对应的向量分别为:
| 主键 | 向量 |
|---|---|
101 | [1.0, 0.0, 0.0, 0.0] |
102 | [0.0, 2.0, 0.0, 0.0] |
103 | [0.0, 0.0, 3.0, 4.0] |
计算过程如下:
0.2 * [1.0, 0.0, 0.0, 0.0] + 0.3 * [0.0, 2.0, 0.0, 0.0] + 0.5 * [0.0, 0.0, 3.0, 4.0] = [0.2, 0.6, 1.5, 2.0]
响应参数:
{ "code": "Success", "message": "The API call was executed successfully.", "request_id": "02175438839168500000000000000000000ffff0a003ee4fc3499", "result": { "op": "vector_weighted_sum", "vector_weighted_sum": { "vector": [0.2, 0.6, 1.5, 2.0], "found_ids": [101, 102, 103], "found_count": 3, "weight_sum": 1.0 } } }
如果请求中部分主键不存在,未命中的主键不会参与计算,对应权重也不会计入 weight_sum。
例如 103 不存在时,响应如下:
{ "code": "Success", "message": "The API call was executed successfully.", "request_id": "02175438839168500000000000000000000ffff0a003ee4fc3499", "result": { "op": "vector_weighted_sum", "vector_weighted_sum": { "vector": [0.2, 0.6, 0.0, 0.0], "found_ids": [101, 102], "found_count": 2, "weight_sum": 0.5 } } }
如果调用方需要加权平均向量,可以在业务侧用以下方式计算:
weighted_avg = vector / weight_sum
当 found_count 为 0 或 weight_sum 为 0 时,调用方需要自行决定兜底策略,不建议直接做除法。
| 场景 | 返回结果 |
|---|---|
全局 count 没有命中数据 | agg.__TOTAL__ 返回 0。 |
分桶 count 没有命中数据 | agg 返回空对象。 |
全局 sum、avg、min、max 没有有效数值 | agg.__TOTAL__ 返回 null。 |
分桶 sum、avg、min、max 没有有效数值 | agg 返回空对象。 |
vector_weighted_sum 的 ids 均未命中 | vector 返回空数组,found_ids 返回空数组,found_count 返回 0,weight_sum 返回 0。 |
sum、avg、min、max 不用 0 表示空结果。0 是合法计算值,null 才表示没有可参与计算的有效数值。
| 限制项 | 说明 |
|---|---|
| 聚合算子 | op 只能取 count、sum、avg、min、max、vector_weighted_sum。 |
| 标量计算字段 | 使用 sum、avg、min、max 时,必须通过 calc_value_on 指定计算字段。该字段必须是已建范围索引的 int64 或 float32 字段。 |
| 分桶字段 | group_by 仅支持已建枚举索引的 string、int64、bool 字段。 |
| 分桶结果规模 | 单次最多返回 10000 个桶。分桶数量较多时,接口不能保证返回所有桶,建议选择低基数字段,或先通过 filter 缩小统计范围。 |
| 标量计算结果 | 当标量计算结果超出数值范围或产生非有限值时,请求会返回参数错误。建议缩小统计范围,或避免对可能溢出的字段做聚合。 |
| 向量聚合输入 | vector_weighted_sum 的 ids 和 weights 必须同时传入,长度必须相同;ids 最多 2000 个,且不能包含重复主键;weights 只能包含有限数值。 |
| 向量聚合能力 | vector_weighted_sum 仅支持包含向量字段或已配置向量化参数的 Collection,不支持 filter、group_by、calc_value_on 和 order。 |
""" pip3 install volcengine """ from volcengine.base.Request import Request import requests, json class ClientForDataApi: def __init__(self, api_key=None, host=None): """ 初始化ClientForDataApi类 :param api_key: VikingDB的API Key :param host: VikingDB的API Host """ if not api_key or not host: raise ValueError("api_key and host are required") self.api_key = api_key self.host = host def prepare_request(self, method, path, params=None, data=None): r = Request() r.set_shema("https") r.set_method(method) r.set_connection_timeout(10) r.set_socket_timeout(10) mheaders = { "Accept": "application/json", "Content-Type": "application/json", "Host": self.host, "Authorization": f"Bearer {self.api_key}", } r.set_headers(mheaders) if params: r.set_query(params) r.set_host(self.host) r.set_path(path) if data is not None: r.set_body(json.dumps(data)) return r def do_req(self, req_method, req_path, req_params, req_body): req = self.prepare_request( method=req_method, path=req_path, params=req_params, data=req_body ) return requests.request( method=req.method, url="https://{}{}".format(self.host, req.path), headers=req.headers, data=req.body, timeout=10000, ) if __name__ == "__main__": import os client = ClientForDataApi( api_key=os.environ.get("VIKINGDB_API_KEY", "***"), # 从环境变量中获取API Key,若未设置则使用默认值 host="api-vikingdb.vikingdb.cn-beijing.volces.com", # 替换为您所在的域名 ) req_method = "POST" req_params = None req_path = "/api/vikingdb/data/agg" req_body = { "collection_name": "test_coll", "index_name": "idx_1", "op": "sum", "calc_value_on": "price", "group_by": "category", "order": "desc", } result = client.do_req( req_method=req_method, req_path=req_path, req_params=req_params, req_body=req_body ) print("req http status code: ", result.status_code) print("req result: \n", result.text)