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 对照
-- prefix
SELECT * FROM salesdata WHERE invoice_number LIKE 'INV-2026%';
-- wildcard(包含)
SELECT * FROM salesdata WHERE invoice_number LIKE '%2026%';
-- fuzzy(拼写容错,PG 需 pg_trgm 扩展)
SELECT * FROM salesdata WHERE material % '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 实现
@Component
public class Doc15FuzzyQuery {
@Autowired
private ElasticsearchClient elasticsearchClient;
/** LIKE 'prefix%' */
public List<Map<String, Object>> prefix(String indexName, String field, String prefix)
throws IOException {
SearchResponse<Map> resp = elasticsearchClient.search(s -> s
.index(indexName)
.query(q -> q.prefix(p -> p.field(field).value(prefix))),
Map.class);
return toSourceList(resp);
}
/** LIKE '%pattern%',pattern 里用 * 和 ? */
public List<Map<String, Object>> wildcard(String indexName, String field, String pattern)
throws IOException {
SearchResponse<Map> resp = elasticsearchClient.search(s -> s
.index(indexName)
.query(q -> q.wildcard(w -> w.field(field).value(pattern))),
Map.class);
return toSourceList(resp);
}
/** 拼写容错 */
public List<Map<String, Object>> fuzzy(String indexName, String field, String value)
throws IOException {
SearchResponse<Map> resp = elasticsearchClient.search(s -> s
.index(indexName)
.query(q -> q.fuzzy(f -> f.field(field).value(value).fuzziness("AUTO"))),
Map.class);
return toSourceList(resp);
}
private List<Map<String, Object>> toSourceList(SearchResponse<Map> resp) {
return resp.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。

4834

被折叠的 条评论
为什么被折叠?



