LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

与产品经理的“模糊”对决:Elasticsearch实现MySQL LIKE '%xxx%'

freeflydom
2025年12月3日 15:52 本文热度 110

曾以为掌握了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实现。

什么是n-gram?

简单说,就是把文本切成固定长度的片段:

原始文本:"苹果手机"
2-gram分词:["苹果", "果手", "手机"]
3-gram分词:["苹果手", "果手机"]

配置n-gram分析器

PUT /products
{
  "settings": {
    "analysis": {
      "analyzer": {
        "ngram_analyzer": {
          "tokenizer": "ngram_tokenizer"
        }
      },
      "tokenizer": {
        "ngram_tokenizer": {
          "type": "ngram",
          "min_gram": 2,  // 最小2个字符
          "max_gram": 3   // 最大3个字符
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "ngram_analyzer",
        "search_analyzer": "standard"
      }
    }
  }
}

实现前后模糊匹配

GET /products/_search
{
  "query": {
    "match_phrase": {
      "name": "果手"
    }
  }
}

效果:成功匹配到"苹果手机"!

付出的代价:

  • ✅ 支持任意位置的子串匹配
  • ❌ 索引体积膨胀3倍以上
  • ❌ 查询性能受影响
  • ❌ 需要精细调整n-gram参数

危险的诱惑:7.9之前的wildcard查询

在调研过程中,我发现ES其实一直都有wildcard查询,但文档里满是红色警告。

揭开wildcard查询的真相

常见误解1: "7.9版本以下只能查keyword字段"
事实: wildcard可以作用于text字段,但匹配的是分词后的term,结果往往出乎意料,不尽人意。

常见误解2: "会进行全索引扫描"
事实: 扫描的是字段倒排索引中的所有term,对每个term进行正则匹配

wildcard查询实战

// 对keyword字段查询(相对可用)
GET /products/_search
{
  "query": {
    "wildcard": {
      "name": {
        "value": "*iPhone*",
        "case_insensitive": true
      }
    }
  }
}
// 对text字段查询(强烈不推荐)
GET /products/_search
{
  "query": {
    "wildcard": {
      "name": {
        "value": "*iphone*"
      }
    }
  }
}

说明:当设置case_insensitive为true时,查询会忽略大小写。

性能灾难:前导通配符*会导致遍历所有term,CPU和内存瞬间飙升,妥妥的集群杀手!


新时代的解决方案:ES 7.9+的wildcard字段类型

就在我纠结要不要接受n-gram的索引膨胀时,突然想起:我们不是准备采购ES 8.x吗?

ES 7.9引入的wildcard字段类型简直就是为此场景量身定制!

技术原理揭秘

  • 智能n-gram索引:底层使用优化的3字符n-gram
  • 二进制doc value:完整保存原始文档,保证匹配精度
  • 专用查询引擎:针对通配符场景深度优化

实际配置和使用

PUT /products
{
  "mappings": {
    "properties": {
      "name": {
        "type": "wildcard"  // 专门为通配符优化的字段类型
      }
    }
  }
}
GET /products/_search
{
  "query": {
    "wildcard": {
      "name": {
        "value": "*果手*"  // 前后模糊匹配
      }
    }
  }
}

性能对比:数字说话

在我们的测试环境中:

方案索引大小平均查询延迟集群影响功能完整性
n-gram + match_phrase原始大小 × 约3倍50ms左右中等
旧版wildcard查询原始大小1000ms+极高风险
wildcard字段类型原始大小 × 约1.4倍25ms左右很低

结果显而易见!


最终技术选型

经过充分的测试和对比,我们最终拍板:

  1. 采购Elasticsearch 8.x集群
  2. 对需要模糊匹配的字段使用wildcard类型
  3. 传统搜索场景继续使用match_phrase等成熟方案
// 最终的映射设计
PUT /products
{
  "mappings": {
    "properties": {
      "name": {
        "type": "wildcard"      // 用于前后模糊匹配
      },
      "description": {
        "type": "text"          // 用于常规全文搜索
      },
      "category": {
        "type": "keyword"       // 用于精确分类匹配
      }
    }
  }
}

当演示结果出来时,产品和用户都很满意:“所以现在输入'果手'真的能找到'苹果手机'了?而且性能还不错?”

“没错,这就是技术演进的力量!”我微笑着回答。

(其实是工期足的力量☺️,工期足够长,资金足够多,什么都能做😊)


总结:Elasticsearch模糊搜索方案对比

搜索方式适用场景优点缺点推荐指数
match常规全文搜索简单易用精度较低⭐⭐⭐⭐
match + operator: "and"多词必须匹配提高相关性顺序不固定⭐⭐⭐
match_phrase精确词组匹配顺序一致不支持模糊⭐⭐⭐⭐
n-gram + match_phrase前后模糊匹配功能完整索引膨胀严重⭐⭐⭐
旧版wildcard查询通配符匹配使用简单性能极差
wildcard字段类型前后模糊匹配性能优秀需要ES 7.9+⭐⭐⭐⭐⭐

技术心得:

从最初的match查询到最终的wildcard字段类型,这条演进之路告诉我们:

  1. 了解业务场景:不同的搜索需求需要不同的技术方案
  2. 理解底层原理:明白分词机制和查询原理才能做出正确选择
  3. 拥抱技术演进:新版本往往用更优雅的方式解决老问题

友情提示: 如果你的产品经理接下来要求实现“深度分页”,请温柔地提醒TA——就连淘宝搜索也只支持100页,这不是技术限制,而是用户体验的最优解!

转自https://www.cnblogs.com/xzqcsj/p/19280639


该文章在 2025/12/3 15:52:21 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved