第二阶段 15 · prefix / wildcard / fuzzy 模糊匹配
📅 2026/7/31 17:55:13
👁️ 阅读次数
📝 编程学习
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. 坑与最佳实践
- 前置通配符
*abc极慢:等于全表扫倒排词典,能避免就避免;必要时用wildcard字段类型或 n-gram。 - 作用在
keyword上:对分词后的text用 wildcard 结果常常反直觉。 - 大小写:
keyword默认大小写敏感,wildcard也是。需要不敏感可加case_insensitive: true(8.x 支持)。 - fuzzy 有性能代价:编辑距离越大越慢,
AUTO通常够用。 - 能用
prefix就别用wildcard:前缀匹配比通配快得多。
下一篇
16-match_phrase-短语.md。
编程学习
技术分享
实战经验