第二阶段 15 · prefix / wildcard / fuzzy 模糊匹配

📅 2026/7/31 17:55:13 👁️ 阅读次数 📝 编程学习
第二阶段 15 · prefix / wildcard / fuzzy 模糊匹配

15 · prefix / wildcard / fuzzy 模糊匹配

阶段:第二阶段 / 查询能力
ES 查询:prefix/wildcard/fuzzy| PostgreSQL 对照:LIKE 'abc%'/LIKE '%x%'/ 模糊纠错


1. 概念

三种「非精确」匹配,都作用在keyword(或 text 的词项)上:

ES 查询作用SQL 对应
prefix前缀匹配LIKE 'abc%'
wildcard通配符匹配(*多字符,?单字符)LIKE '%x%'/LIKE 'a?c'
fuzzy允许拼写误差(编辑距离)PG 没有直接语法(近似pg_trgm

⚠️ 这三种都可能很慢(尤其前置通配*abc),生产环境慎用大范围。


2. PostgreSQL 对照

-- prefixSELECT*FROMsalesdataWHEREinvoice_numberLIKE'INV-2026%';-- wildcard(包含)SELECT*FROMsalesdataWHEREinvoice_numberLIKE'%2026%';-- fuzzy(拼写容错,PG 需 pg_trgm 扩展)SELECT*FROMsalesdataWHEREmaterial%'ThinkPd';-- 相似度

3. ES DSL

prefix(前缀)

GET salesdata_idx/_search { "query": { "prefix": { "invoice_number": "INV-2026" } } }

wildcard(通配符)

GET salesdata_idx/_search { "query": { "wildcard": { "invoice_number": "*2026*" } } }

fuzzy(拼写容错)

GET salesdata_idx/_search { "query": { "fuzzy": { "material": { "value": "ThinkPd", "fuzziness": "AUTO" } } } }

fuzziness: AUTO会根据词长自动决定允许的编辑距离(通常 1~2)。


4. Spring Boot 实现

@ComponentpublicclassDoc15FuzzyQuery{@AutowiredprivateElasticsearchClientelasticsearchClient;/** LIKE 'prefix%' */publicList<Map<String,Object>>prefix(StringindexName,Stringfield,Stringprefix)throwsIOException{SearchResponse<Map>resp=elasticsearchClient.search(s->s.index(indexName).query(q->q.prefix(p->p.field(field).value(prefix))),Map.class);returntoSourceList(resp);}/** LIKE '%pattern%',pattern 里用 * 和 ? */publicList<Map<String,Object>>wildcard(StringindexName,Stringfield,Stringpattern)throwsIOException{SearchResponse<Map>resp=elasticsearchClient.search(s->s.index(indexName).query(q->q.wildcard(w->w.field(field).value(pattern))),Map.class);returntoSourceList(resp);}/** 拼写容错 */publicList<Map<String,Object>>fuzzy(StringindexName,Stringfield,Stringvalue)throwsIOException{SearchResponse<Map>resp=elasticsearchClient.search(s->s.index(indexName).query(q->q.fuzzy(f->f.field(field).value(value).fuzziness("AUTO"))),Map.class);returntoSourceList(resp);}privateList<Map<String,Object>>toSourceList(SearchResponse<Map>resp){returnresp.hits().hits().stream().map(Hit::source).filter(Objects::nonNull).collect(Collectors.toList());}}

5. 坑与最佳实践

  1. 前置通配符*abc极慢:等于全表扫倒排词典,能避免就避免;必要时用wildcard字段类型或 n-gram。
  2. 作用在keyword:对分词后的text用 wildcard 结果常常反直觉。
  3. 大小写keyword默认大小写敏感,wildcard也是。需要不敏感可加case_insensitive: true(8.x 支持)。
  4. fuzzy 有性能代价:编辑距离越大越慢,AUTO通常够用。
  5. 能用prefix就别用wildcard:前缀匹配比通配快得多。

下一篇

16-match_phrase-短语.md