FT.AGGREGATE
在索引上执行查询,并对结果进行分组、聚合或其他处理。
语法
FT.AGGREGATE index query [options]
引入版本:1.1.0
复杂度摘要:O(1)
对索引运行搜索查询并对结果执行聚合转换。
[!NOTE] 此命令将仅返回用户具有读取访问权限的键。
必需参数
index
是执行查询的索引名称。您必须首先使用 FT.CREATE 创建索引。
query
是检索文档的基本过滤查询。它遵循与搜索查询完全相同的语法,包括过滤器、联合、not、可选等。
可选参数
VERBATIM
如果设置,则不会尝试使用词干进行查询扩展,而是逐字搜索查询词。
LOAD {nargs} {identifier} AS {property} …
从源文档加载文档属性。 - identifier 是哈希值和 JSON 的属性名称,或者是 JSON 的 JSON 路径表达式。 - property 是结果中使用的可选名称。如果未提供,则使用 identifier。应该避免这种情况。 - 如果 * 用作 nargs,则加载文档中的所有属性。
聚合所需的属性应存储为 SORTABLE,聚合管道可以以非常低的延迟使用它们。 LOAD 会极大地损害聚合查询的性能,因为每个处理的记录都需要针对 Redis 键执行与 HMGET 等效的操作,当执行数百万个键时,处理时间会很长。
GROUPBY {nargs} {property}
根据一个或多个属性对管道中的结果进行分组。每个组应该至少有一个 减速机,这是一个处理组条目的函数,可以对它们进行计数,也可以执行多个聚合操作(见下文)。
REDUCE {func} {nargs} {arg} … [AS {name}]
使用缩减函数将每组中的匹配结果缩减为单个记录。例如,COUNT 计算组中的记录数。减速器可以使用 AS {name} 可选参数拥有自己的属性名称。如果未给出名称,则结果名称将是reduce 函数和组属性的名称。例如,如果属性 @foo 未给 COUNT_DISTINCT 指定名称,则生成的名称将为 count_distinct(@foo)。
有关更多详细信息,请参阅 支持 GROUPBY 减速器。
SORTBY {nargs} {property} {ASC|DESC} [MAX {num}]
使用属性列表对管道进行排序,直到 SORTBY 点。
- 默认情况下,排序为升序,但可以为每个属性添加
ASC或DESC。 nargs为排序参数个数,包括ASC和DESC,例如SORTBY 4 @foo ASC @bar DESC。MAX用于优化排序,仅对 n 个最大的元素进行排序。虽然它没有连接到LIMIT,但通常只需要SORTBY … MAX即可进行常见查询。
SORTBY 所需的属性应存储为 SORTABLE,以便以非常低的延迟可用。
排序优化:性能针对不同场景下 DIALECT 4 上的排序操作进行了优化: - 跳过排序器 - 当没有任何类型的排序时应用。查询达到 LIMIT 请求的结果后即可返回。 - 部分范围 - 当数字字段上有 SORTBY 子句时应用,没有过滤器或按同一数字字段过滤,查询在足够大的范围上迭代以满足 LIMIT 请求的结果。 - 混合 - 当数字字段和另一个非数字过滤器上存在 SORTBY 子句时应用。某些结果将被过滤,并且初始范围可能不够大。然后迭代器按以下范围倒回,并进行额外的迭代以收集 LIMIT 请求的结果。 - 无优化 - 如果存在按分数或非数字字段排序,则除了检索所有结果并比较它们的值之外别无选择。
计算行为:可选的 WITHCOUNT 参数返回带排序的查询结果的准确计数。此操作处理所有结果以获得准确的计数,其性能低于优化选项(DIALECT 4 上的默认行为)
当与 FT.SEARCH 或 FT.AGGREGATE 一起使用时,您还可以使用 WITHOUTCOUNT 代替 DIALECT 4。
APPLY {expr} AS {name}
对一个或多个属性应用一对一转换,并将结果存储为管道中的新属性,或者使用此转换替换任何属性。
expr 是一个表达式,可用于对数字属性执行算术运算,或可根据其类型应用于属性的函数(见下文),或其任意组合。例如,APPLY "sqrt(@foo)/log(@bar) + 5" AS baz 为管道中的每个记录动态计算此表达式,并将结果存储为名为 baz 的新属性,该属性可以由管道中的进一步 APPLY/SORTBY/GROUPBY/REDUCE 操作引用。
详细信息请参见应用表达式。
LIMIT {offset} {num}
限制结果数量,仅返回从索引 offset(从零开始)开始的 num 结果。如果您只想限制排序操作的输出,那么使用 SORTBY … MAX 会更有效。如果某个键在查询期间过期,则尝试对该键的值进行 load 将返回空数组。
但是,limit 可用于限制不排序的结果,或用于对 SORTBY MAX 确定的 n 个最大结果进行分页。例如,获取前 100 个结果中的第 50-100 个结果最有效地表示为 SORTBY 1 @foo MAX 100 LIMIT 50 50。从 SORTBY 中删除 MAX 会导致管道对 全部 记录进行排序,然后对结果 50-100 进行分页。
FILTER {expr}
使用与每个结果中的值相关的谓词表达式来过滤结果。它们应用于查询后并与管道的当前状态相关。
WITHCURSOR {COUNT} {read_size} [MAXIDLE {idle_time}]
使用比 LIMIT 更快的替代方案扫描部分结果。有关更多详细信息,请参阅 光标API。
TIMEOUT {milliseconds}
如果设置,则覆盖模块的超时参数。
PARAMS {nargs} {name} {value}
定义一个或多个值参数。每个参数都有一个名称和一个值。
您可以通过 $ 后跟参数名称来引用 query 中的参数,例如 $user。搜索查询中对参数名称的每个此类引用都被相应的参数值替换。例如,使用参数定义 PARAMS 4 lon 29.69465 lat 34.95126,表达式 @loc:[$lon $lat 10 km] 将计算为 @loc:[29.69465 34.95126 10 km]。您不能在查询字符串中引用不允许使用具体值的参数,例如在字段名称中,例如 @loc。要使用 PARAMS,请将 DIALECT 设置为 2 或大于 2。
ADDSCORES
ADDSCORES 选项将全文分数值公开给聚合管道。您可以在管道中使用 @__score,如下例所示:
FT.AGGREGATE idx 'hello' ADDSCORES SORTBY 2 @__score DESC
DIALECT {dialect_version}
选择执行查询的方言版本。如果未指定,查询将在模块初始加载期间或通过 FT.CONFIG SET 命令设置的默认方言版本下执行。
返回多个值
请参阅FT.SEARCH 中的返回多个值 可以将DIALECT 指定为FT.AGGREGATE 命令中的参数。如果未指定,则使用 DEFAULT_DIALECT,可以使用 FT.CONFIG SET 或在加载时将其作为参数传递给 redisearch 模块来设置。例如,具有以下文档和索引:
127.0.0.1:6379> JSON.SET doc:1 $ '[{"arr": [1, 2, 3]}, {"val": "hello"}, {"val": "world"}]'
OK
127.0.0.1:6379> FT.CREATE idx ON JSON PREFIX 1 doc: SCHEMA $..arr AS arr NUMERIC $..val AS val TEXT
OK
注意带和不带 DIALECT 3 的不同回复:
127.0.0.1:6379> FT.AGGREGATE idx * LOAD 2 arr val
1) (integer) 1
2) 1) "arr"
2) "[1,2,3]"
3) "val"
4) "hello"
127.0.0.1:6379> FT.AGGREGATE idx * LOAD 2 arr val DIALECT 3
1) (integer) 1
2) 1) "arr"
2) "[[1,2,3]]"
3) "val"
4) "[\"hello\",\"world\"]"
复杂性
不确定性。取决于执行的查询和聚合,但通常与返回的结果数呈线性关系。
示例
Sort page visits by day
查找页面about.html的访问情况,按访问日期分组,统计访问次数,并按天排序。
FT.AGGREGATE idx "@url:\"about.html\""
APPLY "day(@timestamp)" AS day
GROUPBY 2 @day @country
REDUCE count 0 AS num_visits
SORTBY 1 @day
Find most books ever published
找出一年内出版的最多书籍。
FT.AGGREGATE books-idx *
GROUPBY 1 @published_year
REDUCE COUNT 0 AS num_published
GROUPBY 0
REDUCE MAX 1 @num_published AS max_books_published_per_year
Reduce all results
最后一个示例使用 GROUPBY 0。使用 GROUPBY 0 将 REDUCE 函数应用于聚合管道最后一步的所有结果 - 这适用于初始查询和后续 GROUPBY 操作。
搜索经度-73.982254和纬度40.753181 10公里范围内的图书馆,然后用它们的位置与这些坐标之间的距离进行注释。
FT.AGGREGATE libraries-idx "@location:[-73.982254 40.753181 10 km]"
LOAD 1 @location
APPLY "geodistance(@location, -73.982254, 40.753181)"
此处,请注意需要使用 LOAD 来预加载 @location 属性,因为它是 GEO 属性。
接下来,按用户(参与者)统计 GitHub 事件,以产生最活跃的用户。
127.0.0.1:6379> FT.AGGREGATE gh "*" GROUPBY 1 @actor REDUCE COUNT 0 AS num SORTBY 2 @num DESC MAX 10
1) (integer) 284784
2) 1) "actor"
2) "lombiqbot"
3) "num"
4) "22197"
3) 1) "actor"
2) "codepipeline-test"
3) "num"
4) "17746"
4) 1) "actor"
2) "direwolf-github"
3) "num"
4) "10683"
5) 1) "actor"
2) "ogate"
3) "num"
4) "6449"
6) 1) "actor"
2) "openlocalizationtest"
3) "num"
4) "4759"
7) 1) "actor"
2) "digimatic"
3) "num"
4) "3809"
8) 1) "actor"
2) "gugod"
3) "num"
4) "3512"
9) 1) "actor"
2) "xdzou"
3) "num"
4) "3216"
[10](10)) 1) "actor"
2) "opstest"
3) "num"
4) "2863"
11) 1) "actor"
2) "jikker"
3) "num"
4) "2794"
(0.59s)
Use the case function for conditional logic
//Simple mapping
FT.AGGREGATE products "*"
APPLY case(@price > 100, "premium", "standard") AS category
//Nested conditions where an error should be returned
FT.AGGREGATE orders "*"
APPLY case(@status == "pending",
case(@priority == "high", 1, 2),
case(@status == "completed", 3, 4)) AS status_code
//Mapped approach
FT.AGGREGATE orders "*"
APPLY case(@status == "pending", 1, 0) AS is_pending
APPLY case(@is_pending == 1 && @priority == "high", 1,2) AS status_high
APPLY case(@is_pending == 0 && @priority == "high", 3,4) AS status_completed
Collect top documents per group
按类型对电影进行分组,并收集每组排名前 5 的电影,按评分降序排列。返回前 50 个组。
FT.AGGREGATE idx:movies "*"
LOAD 4 @genre @title @rating @year
GROUPBY 1 @genre
REDUCE COLLECT 12 FIELDS 3 @title @rating @year SORTBY 2 @rating DESC LIMIT 0 5 AS top_movies
SORTBY 1 @genre LIMIT 0 50
在此示例中: - LOAD 将 @genre、@title、@rating 和 @year 带入管道。来自已在筹备中的领域的 COLLECT 项目;它不会触发隐式文档加载。使用 FIELDS * 代替显式字段列表将仅返回管道已有的字段,由 LOAD 和任何字段生成操作(例如 APPLY)控制。 - FIELDS 3 @title @rating @year 将这三个字段投影到每个收集的条目中。 - 保留重复项(默认行为,无 DISTINCT 标志)。 - 每组内的文档按 @rating 降序排序。 - 仅返回每组前 5 个文档。 - 仅返回前 50 个组。
Redis Software 与 Redis Cloud 兼容性
| Redis 软件 |
Redis软件 Flex |
Redis Cloud 灵活且每年 |
Redis Cloud 免费和固定 |
说明 |
|---|---|---|---|---|
| ✅ 支持 | ⚠️ 有限 | ✅ 支持 | ✅ 支持 | 对 Flex 数据库 的支持有限。 |
返回值
RESP2
以下之一: * 数组回复,其中每行都是代表单个聚合结果的数组回复。位置 1 处的 整数回复 不代表有效值。 * 简单错误回复 在这些情况下:参数数量不正确、索引不存在、查询语法无效。
RESP3
以下之一: * 地图 具有以下字段: - attributes:属性名称的 数组。 - format: 简单字符串 - 结果格式。 - results:地图 的 数组 包含聚合数据。 - total_results:整数 - 结果总数。 - warning:警告消息的数组。 * 简单错误回复 在这些情况下:参数数量不正确、索引不存在、查询语法无效。
参见
相关主题
资料来源:Redis 官方 FT.AGGREGATE 文档;中文内容参考 Redis 文档许可。