MySQL中ngram解析器与布尔模式查询异常问题排查
问题原因与解决方案
核心原因
ngram解析器的token匹配逻辑
当你设置ngram_token_size=1时,全文索引仅存储单个字符的token。但在布尔模式下,直接输入连续字符(如+CP)会被MySQL视为一个完整的长度为2的term,而索引中不存在该长度的token,因此无法匹配,得分返回0。排序规则的影响
- 使用
utf8mb4_bin时,大小写字符是完全独立的二进制值:索引中存储的是大写的C、P等token,若查询小写的+cp,生成的是小写c、ptoken,无法匹配大写token;你测试中小写查询正常,是因为插入了小写的cp20230817003,其索引token为小写,与查询词匹配。 - 改为
utf8mb4_general_ci后,排序规则不区分大小写,MySQL会自动将查询词的大写转换为小写,同时将连续字符拆分为单个字符token,与索引中的token(不区分大小写)匹配,因此查询正常,但失去了大小写敏感性。
解决方案
方案1:保留大小写敏感性(utf8mb4_bin),拆分查询条件
将连续字符的查询拆分为单个字符的布尔条件,用空格分隔每个term并添加+前缀,表示必须匹配:
-- 原无结果查询 select a.PDGDID, match(a.PDGDID) against ('+CP' in boolean mode) from fulltext_test a; -- 修改后可匹配的查询 select a.PDGDID, match(a.PDGDID) against ('+C +P' in boolean mode) from fulltext_test a;
方案2:匹配连续字符序列,调整ngram_token_size
如果需要匹配CP这类连续的大写字母序列,可将ngram_token_size改为2(需重启MySQL),重建索引后即可直接查询:
-- 修改配置文件中的ngram_token_size=2,重启MySQL服务 -- 重建全文索引 drop index PDGDID on fulltext_test; create fulltext index PDGDID on fulltext_test (PDGDID) with parser ngram; -- 此时查询+CP即可匹配到目标记录 select a.PDGDID, match(a.PDGDID) against ('+CP' in boolean mode) from fulltext_test a;
内容的提问来源于stack exchange,提问作者c521wy
相关产品推荐
相关产品推荐

