*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(如果底层支持)。