MySQL全文检索复数关键词无法匹配单数记录的查询优化咨询
解决方案
你遇到的问题核心是MySQL内置全文检索默认未开启词干提取,也不会自动归一化所有格、单复数格式,按以下两步调整即可满足全部规则:
第一步:统一关键词归一化规则
对入库的search_keywords字段、用户输入的搜索词,统一做以下预处理:
- 全部转为小写,避免大小写匹配偏差
- 去除所有格撇号:将
's直接替换为s,例如men's转mens、women's转womens,统一带撇/不带撇的写法 - 复数转单数:提取名词词干,例如
books转book、hats转hat,轻量场景可直接截取去除末尾s/es后缀即可覆盖大部分常用商品名词
第二步:按场景调整BOOLEAN MODE查询语句
预处理完成后,将搜索词拆分为独立分词,每个分词末尾加通配符*,多关键词场景用+限定必须命中:
单/复数搜索(对应规则1、2)
用户搜索book/books、hat/hats时,预处理后统一得到词干book/hat,查询写法:
SELECT * FROM product WHERE MATCH (search_keywords) AGAINST ("book*" IN BOOLEAN MODE)
可匹配所有词干为book的变体内容。
精确性别衬衫搜索(对应规则3、5)
用户搜索men's shirt/mens shirt时,预处理后得到两个分词mens、shirt,查询写法:
SELECT * FROM product WHERE MATCH (search_keywords) AGAINST ("+mens* +shirt*" IN BOOLEAN MODE)
只会命中同时包含男士标识和衬衫的记录,不会返回女士相关内容。
同理用户搜索women's shirt/womens shirt时,预处理后查询写法:
SELECT * FROM product WHERE MATCH (search_keywords) AGAINST ("+womens* +shirt*" IN BOOLEAN MODE)
只会返回女士衬衫记录。
通用shirt搜索(对应规则4)
用户搜索shirt时,预处理后直接查询:
SELECT * FROM product WHERE MATCH (search_keywords) AGAINST ("shirt*" IN BOOLEAN MODE)
所有包含shirt的记录都会命中,同时返回男士、女士衬衫内容。
进阶优化方案
如果使用MySQL 8.0及以上版本,可开启innodb_ft_enable_stem配置项,开启后InnoDB全文检索会自动处理英文词干提取,不需要手动做单复数转换,仅需预处理所有格撇号即可实现相同效果。
内容的提问来源于stack exchange,提问作者DS9
相关产品推荐
相关产品推荐

