在与产品经理讨论如何使用Elasticsearch实现类似MySQL中的LIKE查询时,以下是一些可能的技术方案和讨论点:### 方案一:使用Elasticsearch的模糊查询(Fuzzy Query)Elasticsearch本身并不直接支持LIKE查

摘要:曾以为掌握了Elasticsearch的match查询就征服了搜索世界——直到产品经理轻叩桌面,抛出一个看似简单的要求:'我们需要像MySQL的LIKE '%关键词%'那样前后通配的模糊
曾以为掌握了Elasticsearch的match查询就征服了搜索世界——直到产品经理轻叩桌面,抛出一个看似简单的要求:"我们需要像MySQL的LIKE '%关键词%'那样前后通配的模糊搜索。" 我嘴角微扬,意识到真正的技术探险才刚刚开始。 引子:一场关于“模糊”需求的拉锯战 “咱们这个搜索功能,用户反馈说经常只记得内容中间的几个字,希望支持前后模糊匹配,就像MySQL里LIKE '%关键词%'那样。” 产品经理眨着期待的大眼睛,而我心里已经开始警铃大作。 “在ES里做前后通配符?这玩意搞不好会把集群搞崩啊!” 我试图挣扎。 “但是竞品都有这个功能了...” 产品经理使出了杀手锏。 经过一番“友好协商”,我们达成共识:工期可以延长,但这个功能必须实现! 送走产品经理,我盯着屏幕陷入沉思:在Elasticsearch里做前后模糊匹配,这确实是个技术挑战。不过话说回来,我们正准备新采购ES集群,和主管评估后决定直接上8.x版本——等等,ES 7.9不是引入了专门的wildcard字段类型吗? 最终方案:基于ES 8.x的wildcard类型字段 + wildcard查询,完美实现前后模糊匹配! 从“分词”这个基础概念说起 要理解ES的模糊搜索,得先搞明白它最核心的概念——分词。 分词的奇妙世界 当你往ES里存入“苹果手机真香”时,背后发生了这样的变化(使用不同分词器,分出来的词可能不一样): 原始文本:"苹果手机真香" ↓ 分词处理 ["苹果", "手机", "真", "香"] 这就是为什么最简单的match查询能够工作: GET /products/_search { "query": { "match": { "name": "苹果手机" } } } 但是,这里藏着第一个坑! 默认情况下,match查询使用or操作符,意味着: // 搜索"苹果手机"可能返回: // - "苹果电脑"(只匹配"苹果") // - "华为手机"(只匹配"手机") // - "苹果手机"(完全匹配) // - "好吃苹果"(只匹配"苹果") 用户想要的是“苹果手机”,结果搜出来一堆不相干的东西,这体验能好吗? 更精确的匹配方式 match + operator "and" - 必须全部包含 GET /products/_search { "query": { "match": { "name": { "query": "苹果手机", "operator": "and" } } } } 效果:必须同时包含"苹果"和"手机"两个词。 进步: 排除了只包含一个词的无关结果。 新问题:顺序不固定!“手机苹果”也会被匹配,这显然不符合正常语言习惯。 match_phrase - 真正的词组匹配 GET /products/_search { "query": { "match_phrase": { "name": "苹果手机" } } } 完美!必须完整包含"苹果手机"这个词组,且顺序一致。 但是... 当测试用例显示:“用户只记得'果手'两个字,怎么搜不到'苹果手机'?” 我意识到,传统的分词搜索有其局限性。 ES 7.9之前的解决方案:n-gram分词器 面对前后模糊匹配的需求,在ES 7.9之前,最成熟的方案就是n-gram分词器 + match_phrase实现。
阅读全文