Elasticsearch 前缀查询(Prefix Query)详解与实战
一、什么是前缀查询?
在日常开发中,我们经常会遇到这样的需求:
- 搜索“java”,希望匹配“javascript”、“java8”、“java工程师”
- 输入关键词的开头部分进行模糊匹配
这时候就可以使用 Elasticsearch 的前缀查询(Prefix Query) 。
👉 简单来说:
前缀查询就是匹配字段中以指定字符串开头的所有文档
二、基本语法
1. DSL 写法
GET /index_name/_search
{
"query": {
"prefix": {
"field_name": {
"value": "java"
}
}
}
}
2. 简写形式
{
"query": {
"prefix": {
"field_name": "java"
}
}
}
三、示例演示
假设我们有如下数据:
{
"name": "java开发"
}
{
"name": "javascript工程师"
}
{
"name": "python开发"
}
执行查询:
{
"query": {
"prefix": {
"name": "java"
}
}
}
返回结果:
- ✅ java开发
- ✅ javascript工程师
- ❌ python开发
四、Prefix Query 的底层原理
Prefix Query 属于 Term-level Query(词项级查询) ,特点是:
- 不会分词
- 直接在倒排索引中查找前缀匹配的 term
👉 执行过程:
- 找到所有以
java开头的 term - 合并这些 term 对应的文档列表
- 返回结果
五、使用注意事项(非常重要)
1. 不要用在 text 类型字段上
"name": {
"type": "text"
}
❌ 错误原因:
- text 会被分词
- prefix 是基于 term 的,不适合
✅ 正确做法:
"name": {
"type": "keyword"
}
或者:
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
查询时用:
"name.keyword"
2. 性能问题
Prefix Query 在以下场景会性能较差:
- 前缀太短(如:a、b)
- 数据量非常大
👉 原因:
- 需要扫描大量 term
3. 不支持打分优化(默认)
Prefix Query 默认:
- 不参与复杂相关性评分
- 更像过滤条件
六、Java 实战(Elasticsearch Client)
1. 使用 RestHighLevelClient(旧版)
PrefixQueryBuilder query = QueryBuilders.prefixQuery("name.keyword", "java");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(query);
SearchRequest request = new SearchRequest("index_name");
request.source(sourceBuilder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
2. 使用新版 Java API Client
SearchResponse<Object> response = esClient.search(s -> s
.index("index_name")
.query(q -> q
.prefix(p -> p
.field("name.keyword")
.value("java")
)
),
Object.class
);
七、Prefix vs Wildcard vs Match
| 查询类型 | 是否分词 | 使用场景 | 性能 |
|---|---|---|---|
| prefix | ❌ 不分词 | 前缀匹配 | ⭐⭐ |
| wildcard | ❌ 不分词 | 任意位置模糊 | ❗较差 |
| match | ✅ 分词 | 全文搜索 | ⭐⭐⭐ |
👉 举例:
- prefix:
java* - wildcard:
*java* - match:语义搜索(分词后匹配)
八、最佳实践建议
✅ 推荐使用场景
- 自动补全(简单版)
- 前缀过滤
- keyword 精确字段查询
❌ 不推荐
- 中文搜索(效果差)
- 长文本模糊匹配
- 高并发 + 大数据量 + 短前缀
九、优化方案(进阶)
如果你是做搜索功能,建议用:
1. edge_ngram(更专业)
"analysis": {
"tokenizer": {
"prefix_tokenizer": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 10,
"token_chars": ["letter", "digit"]
}
}
}
👉 优点:
- 性能好
- 支持搜索联想
2. completion suggester(自动补全)
适用于:
- 搜索框提示
- 推荐词
十、总结
一句话总结:
Prefix Query 是一个简单直接的前缀匹配工具,适合 keyword 字段的小范围匹配,但不适合复杂搜索场景。