统计聚合

更新时间:
复制 MD 格式

使用 Tablestore Python SDK 可对多元索引查询结果执行指标聚合和分组统计。

前提条件

安装Tablestore Python SDK并初始化客户端。

统计聚合功能需要使用 5.2.1 及以上版本,建议使用最新版本的 SDK。

功能说明

统计聚合基于多元索引查询的匹配结果计算指标或生成分组。将指标聚合对象添加到 SearchQuery.aggs,将分组对象添加到 SearchQuery.group_bys;同一请求中的 name 必须唯一,用于从响应中识别结果。只获取统计结果时,可将 limit 设置为 0

功能

说明

Min、Max、Sum、Avg

计算最小值、最大值、总和和平均值。

Count、DistinctCount

统计字段非空值行数和不同值数量。

Percentiles

计算一个或多个百分位值。

TopRows

作为子聚合返回每个分组内排序靠前的行。

GroupByField、GroupByComposite

按单个字段值或多个字段组合分组。

GroupByRange、GroupByGeoDistance、GroupByFilter

按数值范围、地理距离或过滤条件分组。

GroupByHistogram、GroupByDateHistogram、GroupByGeoGrid

生成数值直方图、日期直方图或 GeoHash 网格分组。

重要

用于统计聚合的多元索引字段必须启用排序与统计聚合。不同聚合和分组支持的字段类型不同。同一层级最多配置 5 个分组。去重行数、百分位数和字段值分组采用近似计算;聚合数量多或嵌套层级深会增加请求复杂度并影响响应速度。

以下示例对 price 字段计算最小值、最大值和平均值,并按 category 分组统计行数。

search_query = SearchQuery(
    MatchAllQuery(),
    limit=0,
    aggs=[
        Min("price", name="min_price"),
        Max("price", name="max_price"),
        Avg("price", name="avg_price"),
    ],
    group_bys=[
        GroupByField("category", name="by_category"),
    ],
)
response = client.search(
    "example_table",
    "example_index",
    search_query,
)
for result in response.agg_results:
    print(result.name, result.value)
for result in response.group_by_results:
    print(result.name, result.items)

参数说明

查询请求

search 方法包含以下参数。

名称

类型

说明

table_name(必选)

str

数据表名称。

index_name(必选)

str

多元索引名称。

search_query(必选)

SearchQuery

查询条件和统计聚合配置。

columns_to_get(可选)

ColumnsToGet

返回列配置。未设置时只返回主键列。

routing_keys(可选)

list

自定义路由字段对应的主键值列表。未配置自定义路由时无需设置。

timeout_s(可选)

int

请求级超时时间,单位为秒。未设置时使用客户端默认超时时间。

查询配置

search_query 的类型为 SearchQuery,包含以下与统计聚合相关的参数。

名称

类型

说明

query(必选)

Query

统计范围对应的查询条件。统计全部数据时设置为 MatchAllQuery

aggs(可选)

list[Agg]

指标聚合列表,可组合多个不同名称的聚合。

group_bys(可选)

list[BaseGroupBy]

分组列表,可组合多个不同名称的分组。

limit(可选)

int

查询返回行数。只获取统计结果时设置为 0

指标聚合

以下各对象添加到 search_query.aggsfield 为聚合字段,name 为结果名称,missing_value 表示字段缺失时用于参与计算的值;未设置 missing_value 时忽略缺少该字段的行。

Min、Max 和 Avg

名称

类型

说明

field(必选)

str

聚合字段,支持 LongDoubleDate

missing_value(可选)

str / int / float

字段缺失时参与计算的值。

name(可选)

str

聚合名称,默认分别为 minmaxavg

Sum

名称

类型

说明

field(必选)

str

聚合字段,支持 LongDouble

missing_value(可选)

int / float

字段缺失时用于求和的值。

name(可选)

str

聚合名称,默认值为 sum

Count

名称

类型

说明

field(必选)

str

要统计非空值行数的字段,支持 LongDoubleBooleanKeywordDateGeoPoint

name(可选)

str

聚合名称,默认值为 count

DistinctCount

名称

类型

说明

field(必选)

str

要统计不同值数量的字段,支持 LongDoubleBooleanKeywordDateGeoPoint

missing_value(可选)

str / int / float / bool

字段缺失时参与去重统计的值。

name(可选)

str

聚合名称,默认值为 distinct_count

Percentiles

名称

类型

说明

field(必选)

str

聚合字段,支持 LongDoubleDate

percentiles_list(必选)

list[float]

要计算的百分位列表,例如 [50, 90, 99]

missing_value(可选)

str / int / float

字段缺失时参与计算的值。

name(可选)

str

聚合名称,默认值为 percentiles

TopRows

名称

类型

说明

limit(必选)

int

每个分组内最多返回的行数。

sort(必选)

Sort

分组内行的排序方式。

name(可选)

str

聚合名称,默认值为 top_rows

说明

DistinctCount 为近似统计:不同值少于 10,000 时结果接近精确值;达到 1 亿时误差约为 2%。Percentiles 也为近似统计,较极端的百分位通常比中位数更准确。TopRows 仅作为分组的子聚合使用。

分组

以下各对象添加到 search_query.group_byssub_aggssub_group_bys 可分别对每个分组继续执行子指标聚合和子分组。

GroupByField

名称

类型

说明

field_name(必选)

str

分组字段,支持 LongDoubleBooleanKeywordDate

size(可选)

int

返回分组数,默认值为 10,最大值为 2000

group_by_sort(可选)

list

分组排序规则。默认按行数降序,支持 GroupKeySortRowCountSortSubAggSort

sub_aggs(可选)

list[Agg]

子指标聚合。

sub_group_bys(可选)

list[BaseGroupBy]

子分组。

name(可选)

str

分组名称,默认值为 group_by_field

GroupByComposite

名称

类型

说明

sources(必选)

list[BaseGroupBy]

多字段分组源,最多 32 个。支持 GroupByFieldGroupByHistogramGroupByDateHistogram

size(可选)

int

返回分组数,默认值为 10,最大值为 2000

next_token(可选)

bytes

下一页分组凭证。首次请求不设置。

suggested_size(可选)

int

高吞吐计算场景的软限制,不能与 size 同时设置。

sub_aggs(可选)

list[Agg]

子指标聚合。

sub_group_bys(可选)

list[BaseGroupBy]

子分组。GroupByComposite 不能作为其他分组的子分组。

name(可选)

str

分组名称,默认值为 group_by_composite

GroupByRange

名称

类型

说明

field_name(必选)

str

分组字段,支持 LongDouble

ranges(必选)

list[tuple]

左闭右开范围列表,例如 [(0, 100), (100, 200)]

sub_aggs(可选)

list[Agg]

子指标聚合。

sub_group_bys(可选)

list[BaseGroupBy]

子分组。

name(可选)

str

分组名称,默认值为 group_by_range

GroupByGeoDistance

名称

类型

说明

field_name(必选)

str

GeoPoint 类型分组字段。

origin(必选)

GeoPoint

中心点,构造参数依次为纬度和经度。

ranges(必选)

list[tuple]

距离范围列表,单位为米,采用左闭右开区间。

sub_aggs(可选)

list[Agg]

子指标聚合。

sub_group_bys(可选)

list[BaseGroupBy]

子分组。

name(可选)

str

分组名称,默认值为 group_by_geo_distance

GroupByFilter

名称

类型

说明

filters(必选)

list[Query]

过滤条件列表,结果顺序与条件顺序一致。

sub_aggs(可选)

list[Agg]

子指标聚合。

sub_group_bys(可选)

list[BaseGroupBy]

子分组。

name(可选)

str

分组名称,默认值为 group_by_filter

GroupByHistogram

名称

类型

说明

field_name(必选)

str

分组字段,支持 LongDouble

interval(必选)

int / float

数值直方图间隔。

field_range(必选)

FieldRange

统计范围。(max-min)/interval 不能超过 2000

missing_value(可选)

int / float

字段缺失时参与直方图统计的值。

min_doc_count(可选)

int

分组内最少行数,行数不足的桶不返回。

group_by_sort(可选)

list

分组排序规则。

sub_aggs(可选)

list[Agg]

子指标聚合。

sub_group_bys(可选)

list[BaseGroupBy]

子分组。

name(可选)

str

分组名称,默认值为 group_by_histogram

GroupByDateHistogram

名称

类型

说明

field_name(必选)

str

Date 类型分组字段。

interval(必选)

DateTimeValue

日期或时间间隔,由数值和 DateTimeUnit 组成。

field_range(必选)

FieldRange

统计范围。虽然 Python 构造方法允许省略,但服务端要求必须设置。

missing(可选)

str

字段缺失时参与日期直方图统计的日期值。

min_doc_count(可选)

int

分组内最少行数,行数不足的桶不返回。

time_zone(可选)

str

时区,格式为 +hh:mm-hh:mm,例如 +08:00

group_by_sort(可选)

list

分组排序规则。

offset(可选)

DateTimeValue

桶边界相对默认起点的偏移量。

sub_aggs(可选)

list[Agg]

子指标聚合。

sub_group_bys(可选)

list[BaseGroupBy]

子分组。

name(可选)

str

分组名称,默认值为 group_by_date_histogram

GroupByGeoGrid

名称

类型

说明

field_name(必选)

str

GeoPoint 类型分组字段。

precision(必选)

GeoHashPrecision

GeoHash 网格精度,枚举序号越大,网格越小。

size(可选)

int

返回的网格分组数。

sub_aggs(可选)

list[Agg]

子指标聚合。

sub_group_bys(可选)

list[BaseGroupBy]

子分组。

name(可选)

str

分组名称,默认值为 group_by_geo_grid

说明

GroupByComposite 需要使用 Python SDK 6.4.4 及以上版本。分组结果较多时,设置 size 并使用返回结果的 next_token 翻页,直到凭证为空。

返回列

columns_to_get 的类型为 ColumnsToGet,包含以下参数。

名称

类型

说明

column_names(可选)

list[str]

要返回的属性列名称。仅 return_typeSPECIFIED 时设置。

return_type(可选)

ColumnReturnType

返回列模式。NONE(默认)仅返回主键列;SPECIFIED 返回指定属性列;ALL 返回数据表全部属性列;ALL_FROM_INDEX 返回索引中已存储的全部属性列。

返回值

search 方法返回 SearchResponse。核心字段如下。

字段

类型

说明

rows

list[Row]

本次查询返回的行数据,数量不超过 limit

next_token

bytes

下一页凭证。值为空时表示没有更多数据。

total_count

int

匹配行数,取决于 get_total_count 配置。

is_all_succeed

bool

是否已成功查询全部索引分区。值为 False 时返回的是部分结果。

agg_results

list[AggResult]

指标聚合结果。未配置 aggs 时为空。

group_by_results

list[GroupByResult]

分组结果。未配置 group_bys 时为空。

search_hits

list[SearchHit]

查询命中结果,包含行数据、相关性得分和高亮结果等扩展信息。

agg_results 中每项通过 namevalue 标识聚合及其值;group_by_results 中每项通过 nameitems 返回各分组键、行数、子聚合和子分组。GroupByComposite 结果还包含 source_group_by_names 和用于继续读取的 next_token;每个分组的 keys 为字符串列表,与 sources 顺序一致,字段值为空时对应位置为 None

兼容 Tuple 返回格式

Tablestore Python SDK 5.2.0 开始将查询接口的返回值由 Tuple 调整为响应对象,5.1.0 及以下版本直接返回 Tuple。5.2.1 及以上版本可调用 SearchResponse.v1_response() 获取与旧版本兼容的 Tuple。新代码建议直接访问 SearchResponse 的属性,避免返回字段扩展后解包数量不匹配。

(
    rows,
    next_token,
    total_count,
    is_all_succeed,
    agg_results,
    group_by_results,
    search_hits,
) = response.v1_response()

场景示例

使用多字段分组并翻页

以下示例按 categoryprice 组合分组,每次返回两个分组。

sources = [
    GroupByField("category", name="category_source"),
    GroupByField("price", name="price_source"),
]
next_token = None
all_items = []

while True:
    group_by = GroupByComposite(
        sources,
        size=2,
        next_token=next_token,
        name="by_category_and_price",
    )
    response = client.search(
        "example_table",
        "example_index",
        SearchQuery(MatchAllQuery(), limit=0, group_bys=[group_by]),
    )
    result = response.group_by_results[0]
    all_items.extend(result.items)
    next_token = result.next_token
    if not next_token:
        break

for item in all_items:
    print(item.keys, item.row_count)

生成日期直方图和地理网格

以下示例按天生成日期直方图,并按约 39 km × 19 km 的 GeoHash 网格划分地理位置。

group_bys = [
    GroupByDateHistogram(
        "event_date",
        DateTimeValue(1, DateTimeUnit.DAY),
        field_range=FieldRange("2026-08-01", "2026-08-04"),
        name="by_day",
    ),
    GroupByGeoGrid(
        "location",
        GeoHashPrecision.GHP_39KM_19KM_4,
        name="by_geo_grid",
    ),
]
response = client.search(
    "example_table",
    "example_index",
    SearchQuery(MatchAllQuery(), limit=0, group_bys=group_bys),
)
for result in response.group_by_results:
    print(result.name, result.items)