Redisearch全文检索如何实现后缀匹配、字符串包含查询
RediSearch默认文本索引基于前缀分词逻辑实现,原生仅支持前缀通配匹配(即关键词后接*,比如你之前执行成功的god*查询),不支持通配符放在词首的后缀匹配、任意位置子串匹配,因此直接写@title:*father、@title:*fath*这类语法默认无法生效。
你执行的AGGREGATE查询失败,核心原因是当前使用的RediSearch版本为2.4.8,该版本FILTER子句无法直接读取TEXT类型的分词字段做字符串函数运算,且contains函数调用时未正确加载字段、字段引用格式错误。
方案1:建索引时开启后缀索引(推荐,性能最优)
RediSearch 2.4及以上版本支持为TEXT字段配置后缀Trie索引,开启后即可原生支持后缀、任意子串匹配,操作步骤如下:- 删除原有旧索引
FT.DROPINDEX idx:movies- 重建索引,为title字段添加
SUFFIXTRIE配置
FT.CREATE idx:movies ON hash PREFIX 1 "movies:" SCHEMA title TEXT SORTABLE SUFFIXTRIE release_year NUMERIC SORTABLE rating NUMERIC SORTABLE genre TAG SORTABLE索引重建完成后,之前无法执行的两类查询可直接正常运行:
# 查询标题以father结尾的影片 FT.SEARCH idx:movies @title:*father SORTBY release_year ASC RETURN 2 title release_year # 查询标题包含fath的影片 FT.SEARCH idx:movies @title:*fath* SORTBY release_year ASC RETURN 2 title release_year注意:开启
SUFFIXTRIE会小幅增加索引存储占用,子串/后缀匹配性能略低于纯前缀匹配,但远高于全表扫描类方案。方案2:新增TAG类型字段存储原始文本
若不想调整现有TEXT字段的索引配置,可以新增一个TAG类型字段同步存储标题原始值,TAG字段默认支持前后位置的通配符匹配:
建索引示例:FT.CREATE idx:movies ON hash PREFIX 1 "movies:" SCHEMA title TEXT SORTABLE title_raw TAG SORTABLE release_year NUMERIC SORTABLE rating NUMERIC SORTABLE genre TAG SORTABLE写入数据时同步给
title_raw字段赋值相同的标题内容,之后即可通过TAG字段做子串匹配:FT.SEARCH idx:movies @title_raw:{*father*} RETURN 2 title release_year注意:TAG字段不会做分词,匹配逻辑针对完整字符串执行,仅适合标题这类短文本字段,长文本场景不适用。
方案3:修正AGGREGATE查询写法(仅适合小数据量临时使用,性能差)
若不想修改现有索引结构,可以调整聚合查询逻辑,先通过LOAD子句加载原始字段值,再执行contains过滤,正确写法如下:FT.AGGREGATE idx:movies "*" LOAD 1 title FILTER "contains(@title, 'father')"该方案会全表扫描所有索引文档,加载字段值后逐行做字符串判断,数据量较大时延迟会非常高,不建议生产环境使用。
内容的提问来源于stack exchange,提问作者Teebs

