*Redis FT.SEARCH 命令
FT.SEARCH 用于在 RediSearch 索引中执行全文搜索查询,支持复杂的布尔查询、范围过滤、排序和分页。
*语法
FT.SEARCH index_name query [NOCONTENT] [VERBATIM] [NOSTOPWORDS] [WITHSCORES] [WITHPAYLOADS] [WITHSORTKEYS] [FILTER numeric_field min max [FILTER numeric_field min max ...]] [GEOFILTER geo_field lon lat radius m|km|mi|ft] [INKEYS count key [key ...]] [INFIELDS count field [field ...]] [RETURN count field [field ...]] [SUMMARIZE [FIELDS count field [field ...]] [FRAGS num] [LEN fragsize] [SEPARATOR separator]] [HIGHLIGHT [FIELDS count field [field ...]] [TAGS open close]] [SLOP slop] [TIMEOUT timeout] [INORDER] [LANGUAGE lang] [EXPANDER expander] [SCORER scorer] [SORTBY field [ASC|DESC] [WITHCOUNT]] [LIMIT offset num] [PARAMS count name value [name value ...]] [DIALECT dialect] [EXPPLAINSCORE]
*参数说明
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| index_name | String | 是 | 索引名称 |
| query | String | 是 | 搜索查询表达式 |
| NOCONTENT | Flag | 否 | 仅返回文档 ID,不返回字段内容 |
| VERBATIM | Flag | 否 | 禁用词干提取和扩展 |
| NOSTOPWORDS | Flag | 否 | 不忽略停用词 |
| WITHSCORES | Flag | 否 | 返回相关性评分 |
| WITHPAYLOADS | Flag | 否 | 返回 payloads(仅 Legacy 模式) |
| WITHSORTKEYS | Flag | 否 | 返回排序键值 |
| FILTER | 条件 | 否 | 对数值字段进行范围过滤 |
| GEOFILTER | 条件 | 否 | 对 GEO 字段进行地理范围过滤 |
| INKEYS | 条件 | 否 | 限制仅在指定 key 中搜索 |
| INFIELDS | 条件 | 否 | 限制仅在指定字段中搜索 |
| RETURN | 条件 | 否 | 指定返回的字段列表 |
| SUMMARIZE | 条件 | 否 | 返回字段摘要(片段) |
| HIGHLIGHT | 条件 | 否 | 高亮匹配的关键词 |
| SLOP | Integer | 否 | 短语查询中词项之间的最大距离 |
| TIMEOUT | Integer | 否 | 查询超时时间(毫秒) |
| INORDER | Flag | 否 | 要求词项按查询中的顺序出现 |
| LANGUAGE | String | 否 | 指定语言(用于词干提取) |
| EXPANDER | String | 否 | 指定查询扩展器 |
| SCORER | String | 否 | 指定评分算法(TFIDF、BM25、DISMAX 等) |
| SORTBY | 条件 | 否 | 按指定字段排序 |
| LIMIT | 分页 | 否 | 分页参数(offset num) |
| PARAMS | 参数 | 否 | 绑定查询参数(用于 Dialect 2+) |
| DIALECT | Integer | 否 | 查询方言版本(1、2、3、4) |
| EXPLAINSCORE | Flag | 否 | 解释评分计算过程 |
*返回值
- 查询结果数组:
- 第一个元素:总匹配数量(或 LIMIT 前的结果数,取决于 Dialect)
- 后续元素:每个文档结果(文档 ID + 字段内容)
- 若使用 NOCONTENT:仅返回文档 ID
- 若使用 WITHSCORES:每个文档后跟随评分值
- 空查询或无结果:返回
1) (empty array)或仅包含0的数组
*时间复杂度
O(n),其中 n 是查询结果数量。实际复杂度取决于查询条件、索引结构和过滤条件。
*示例
*基本搜索
> FT.SEARCH myIndex "hello world"
1) "1"
2) "doc:100"
3) 1) "title"
2) "hello world example"
3) "content"
4) "this is a hello world article about redis"
*带过滤条件的搜索
> FT.SEARCH myIndex "redis" FILTER price 10 100 SORTBY price ASC LIMIT 0 10
1) "3"
2) "doc:200"
3) 1) "title"
2) "redis tutorial"
3) "price"
4) "25"
4) "doc:201"
5) 1) "title"
2) "advanced redis"
3) "price"
4) "50"
6) "doc:202"
7) 1) "title"
2) "redis search guide"
3) "price"
4) "75"
*使用 Dialect 2 进行参数化查询
> FT.SEARCH myIndex "@title:$keyword" PARAMS 2 keyword "redis" DIALECT 2
1) "2"
2) "doc:100"
3) 1) "title"
2) "redis search"
3) "content"
4) "redis search module"
4) "doc:101"
5) 1) "title"
2) "redis tutorial"
3) "content"
4) "redis basics"
*常见错误
| 错误 | 原因 | 解决 |
|---|---|---|
| Syntax error at offset ... | 查询语法错误 | 检查查询表达式的引号、括号匹配 |
| Unknown index name | 索引不存在 | 确认索引已创建,名称拼写正确 |
| Property 'xxx' not loaded | 字段未加载 | 使用 RETURN 指定字段,或检查索引中是否定义了该字段 |
| GEO filter invalid | 地理过滤参数错误 | 检查经纬度范围和半径单位(m/km/mi/ft) |
| Timeout limit reached | 查询超时 | 增加 TIMEOUT 参数,或优化查询条件 |
| Missing param 'xxx' | 参数化查询缺少参数 | 检查 PARAMS 是否正确定义 |
*最佳实践
- 生产环境推荐使用 Dialect 2 或更高版本,支持参数化查询和更丰富的语法
- 对大数据量查询使用 LIMIT 分页,避免一次性返回过多结果
- 使用 NOCONTENT 仅需文档 ID 时减少数据传输
- 对高频查询字段设置 SORTABLE 属性以优化排序性能
- 使用 FILTER 替代数值范围查询,性能更优
- 短语查询使用双引号,如
"exact phrase" - 使用
@field:term语法限定字段搜索,提升精确度和性能 - 设置合理的 TIMEOUT 防止慢查询影响系统
*FAQ
Q1: FT.SEARCH 和 FT.AGGREGATE 有什么区别? A: FT.SEARCH 用于搜索并返回文档内容,FT.AGGREGATE 用于数据聚合(分组、统计、计算)。FT.SEARCH 底层也会使用聚合管道,但语法更简洁,专注于返回文档。
Q2: 为什么总匹配数有时不准确?
A: 在 Dialect 1 中,LIMIT 前的总匹配数可能不精确(近似值)。使用 Dialect 2+ 或设置 WITHCOUNT 可获得精确计数,但性能开销更大。
Q3: 如何实现 OR 和 AND 查询?
A: 默认词项之间是 OR 关系(如 hello world 匹配 hello 或 world)。使用 | 显式表示 OR,hello | world。AND 使用空格或 &(Dialect 2+)。否定使用 -(如 hello -world)。
Q4: 支持中文搜索吗?
A: 支持。对于中文,建议使用 Dialect 2+ 的 PARAMS 参数化查询,并注意中文分词需要合理配置。可在创建索引时通过 LANGUAGE 指定 chinese(如果底层支持)。