Elasticsearch 前缀查询(Prefix Query)详解与实战

3 阅读2分钟

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

👉 执行过程:

  1. 找到所有以 java 开头的 term
  2. 合并这些 term 对应的文档列表
  3. 返回结果

五、使用注意事项(非常重要)

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 字段的小范围匹配,但不适合复杂搜索场景。