聚合查询
对查询结果进行分组和聚合
聚合查询允许您执行以下操作
- 应用简单的映射函数。
- 根据字段值对数据进行分组。
- 对分组数据应用聚合函数。
本文介绍了 FT.AGGREGATE 命令的基本用法。有关更多详细信息,请参阅 命令规范 和 聚合参考文档。
本文中的示例使用具有以下字段的架构
字段名称 | 字段类型 |
---|---|
条件 |
TAG |
price |
NUMERIC |
简单映射
APPLY
子句允许您将简单的映射函数应用于基于查询表达式返回的结果集。
FT.AGGREGATE index "query_expr" LOAD n "field_1" .. "field_n" APPLY "function_expr" AS "result_field"
以下是查询语法更详细的说明
- 查询表达式:你可以使用与
FT.SEARCH
命令相同的查询表达式。你可以用本文档的 查询主题 中解释的任何表达式替换query_expr
。向量搜索查询是个例外。你不能将向量搜索与聚合查询结合使用。 - 已加载字段:如果字段值尚未加载到聚合管道中,你可以通过
LOAD
子句强制它们出现。此子句采用字段数 (n
),后跟字段名称 ("field_1" .. "field_n"
)。 - 映射函数:此映射函数对字段值进行操作。特定字段在函数表达式中引用为
@field_name
。结果返回为result_field
。
以下示例展示了如何计算新自行车的折扣价
FT.AGGREGATE idx:bicycle "@condition:{new}" LOAD 2 "__key" "price" APPLY "@price - (@price * 0.1)" AS "discounted"
字段 __key
是一个内置字段。
此查询的输出是
1) "1"
2) 1) "__key"
1) "bicycle:0"
2) "price"
3) "270"
4) "discounted"
5) "243"
3) 1) "__key"
1) "bicycle:5"
2) "price"
3) "810"
4) "discounted"
5) "729"
4) 1) "__key"
1) "bicycle:6"
2) "price"
3) "2300"
4) "discounted"
5) "2070"
...
使用聚合进行分组
上一个示例未对数据进行分组。你可以按照以下方式根据一个或多个条件对数据进行分组和聚合
FT.AGGREGATE index "query_expr" ... GROUPBY n "field_1" .. "field_n" REDUCE AGG_FUNC m "@field_param_1" .. "@field_param_m" AS "aggregated_result_field"
以下是其他结构的说明
- 分组:你可以按一个或多个字段进行分组。然后,字段值的每个有序序列定义一个组。还可以按先前
APPLY ... AS
产生的值进行分组。 - 聚合:你必须用一个受支持的聚合函数(例如
SUM
或COUNT
)替换AGG_FUNC
。可以在 聚合参考文档 中找到函数的完整列表。用你选择的值替换aggregated_result_field
。
以下查询展示了如何按字段 condition
进行分组,并根据先前派生的 price_category
应用约简。表达式 @price<1000
表示如果自行车的价格低于 1000 美元,则其价格类别为 1
。否则,其价格类别为 0
。输出是按价格类别分组的经济型自行车数量。
FT.AGGREGATE idx:bicycle "*" LOAD 1 price APPLY "@price<1000" AS price_category GROUPBY 1 @condition REDUCE SUM 1 "@price_category" AS "num_affordable"
1) "3"
2) 1) "condition"
1) "refurbished"
2) "num_affordable"
3) "1"
3) 1) "condition"
1) "used"
2) "num_affordable"
3) "1"
4) 1) "condition"
1) "new"
2) "num_affordable"
3) "3"
注意
你还可以使用 FT.AGGREGATE 创建更复杂的聚合管道。可以在一个 GROUPBY
子句下应用多个约简函数。此外,你还可以链接分组并混合其他映射步骤(例如 GROUPBY ... REDUCE ... APPLY ... GROUPBY ... REDUCE
)
不分组的聚合
您不能在 `GROUPBY` 子句之外使用聚合函数,但您可以以聚合发生在跨越所有文档的单个组上的方式构建您的管道。如果您的文档不共享一个公共属性,您可以通过额外的 `APPLY` 步骤添加它。
以下是一个示例,它在计算所有具有该类型的文档之前向每个文档添加类型属性 `bicycle`
FT.AGGREGATE idx:bicycle "*" APPLY "'bicycle'" AS type GROUPBY 1 @type REDUCE COUNT 0 AS num_total
结果是
1) "1"
2) 1) "type"
1) "bicycle"
2) "num_total"
3) "10"
不聚合的分组
有时需要对数据进行分组而不应用数学聚合函数。如果您需要一个分组的值列表,那么 `TOLIST` 函数将很有帮助。
以下示例演示如何按 `condition` 对所有自行车进行分组
FT.AGGREGATE idx:bicycle "*" LOAD 1 "__key" GROUPBY 1 "@condition" REDUCE TOLIST 1 "__key" AS bicylces
此查询的输出是
1) "3"
2) 1) "condition"
1) "refurbished"
2) "bicylces"
3) 1) "bicycle:9"
3) 1) "condition"
1) "used"
2) "bicylces"
3) 1) "bicycle:1"
1) "bicycle:2"
2) "bicycle:3"
3) "bicycle:4"
4) 1) "condition"
1) "new"
2) "bicylces"
3) 1) "bicycle:0"
1) "bicycle:5"
2) "bicycle:6"
3) "bicycle:8"
4) "bicycle:7"