Elasticsearch可通过ngram、edge_ngram、wildcard、fuzzy及双写同步五种方式替代MySQL的LIKE '%keyword%' 模糊查询,兼顾性能、精度与适用场景。

如果您在高并发、大数据量场景下仍依赖MySQL的LIKE '%keyword%' 进行模糊匹配,则查询将被迫执行全表扫描,响应延迟显著升高。以下是使用Elasticsearch替代该类MySQL模糊查询的多种可行路径:
一、采用ngram分词器构建子串索引
ngram分词器可将原始文本切分为连续字符序列(如“手机”→“手”、“手机”、“机”),使任意子串均可命中倒排索引,从而模拟MySQL中LIKE '%XX%' 的行为。该方式不依赖通配符,避免wildcard查询的性能陷阱。
1、在索引创建时定义ngram分析器:
2、为目标字段指定analyzer为自定义ngram_analyzer:
3、插入文档后,对“华为手机”进行搜索时,输入“华”“为手”“机”等任意子串均可召回包含该子串的文档。
二、启用edge_ngram实现前缀+中缀混合匹配
edge_ngram仅从词首生成ngram(如“手机壳”→“手”“手机”“手机壳”),适用于前缀模糊需求;但通过配合multi-field策略,可在同一字段上同时暴露standard与edge_ngram两种视图,兼顾前缀与部分中缀匹配能力。
1、在mapping中为name字段声明sub-fields:
2、向name.edge_ngram写入数据时自动触发分词并建立索引:
3、对“手机”发起match查询时,优先走name.edge_ngram子字段;对含中间字符的模糊需求(如“购手机”),则改用name.standard配合match_phrase_prefix或bool should组合。
三、使用wildcard查询(低频、小数据集适用)
wildcard查询直接支持?和*通配符语法,语义最贴近MySQL LIKE,但其底层需遍历全部词项,不利用Term Index加速,故仅适合日均查询量低、索引总词项数低于10万的轻量级场景。
1、确保目标字段未被text类型默认分词,应设为keyword类型以保留原始字符串:
2、执行如下DSL查询,等效于MySQL中WHERE name LIKE '%xiaomi%':
3、必须限制查询频率,并禁止在高QPS接口中直接暴露该能力。
四、结合fuzzy查询处理拼写容错型模糊匹配
fuzzy查询基于编辑距离匹配相似词项,适用于用户输入存在错别字、简写或发音近似的情形(如搜“xiaomni”仍能命中“xiaomi”)。它不解决任意子串匹配,但在“近似关键词”模糊场景下具备更高精度与性能。
1、对已用standard或ik_smart分词的text字段启用fuzzy参数:
2、设置fuzziness为AUTO或具体数值(如1或2),控制允许的字符替换/插入/删除数量:
3、当原始数据已标准化且用户输入稳定时,fuzzy不宜作为LIKE '%XX%' 的通用替代方案。
五、双写+异步补全:MySQL与ES协同模糊路由
该方案不完全替代MySQL,而是构建查询路由层:结构化条件走MySQL,模糊文本条件自动转发至ES。通过Logstash或Flink CDC监听MySQL binlog,实时同步变更至ES,保障两端数据最终一致。
1、在应用层封装统一search接口,根据查询参数特征判断路由目标:
2、配置Logstash pipeline,过滤出name、description等需模糊检索的字段,写入ES对应索引:
3、所有写操作必须保留MySQL主库为唯一事实源,ES仅作为只读搜索加速层。


















