深入学习 ElasticSearch 的搜索(一):先理解 Query DSL
深入学习 ElasticSearch 的搜索(一):先理解 Query DSL
前面已经整理过 ElasticSearch 的安装、插件管理、中文分词和倒排索引。理解这些基础后,再看搜索语法会清楚很多。
ElasticSearch 的搜索不是简单的字符串包含判断,而是围绕下面几件事展开:
- 字段是否分词
- 查询内容是否分词
- 查询走的是全文检索还是精确匹配
- 多个条件之间是 AND、OR 还是 NOT
- 命中文档如何计算相关性评分
这一篇先做总览,重点理解 ElasticSearch 的 Query DSL 怎么写,以及 match、match_phrase、term、bool 这几类查询分别适合什么场景。
一、准备一个测试索引
为了后面几篇文章都能复用,先准备一个简单的文章索引。
PUT article_search
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "standard"
},
"content": {
"type": "text",
"analyzer": "standard"
},
"category": {
"type": "keyword"
},
"status": {
"type": "keyword"
},
"author": {
"type": "keyword"
},
"views": {
"type": "integer"
},
"created_at": {
"type": "date"
}
}
}
}
这里有两类字段:
text:会分词,适合全文检索keyword:不分词,适合精确匹配、过滤、聚合、排序
这也是后面理解 match 和 term 差异的关键。
二、写入测试数据
写入几条文档:
POST article_search/_doc/1
{
"title": "ElasticSearch 入门教程",
"content": "本文介绍 ElasticSearch 的安装、索引、倒排索引和基础搜索。",
"category": "elasticsearch",
"status": "published",
"author": "admin",
"views": 120,
"created_at": "2026-04-01"
}
POST article_search/_doc/2
{
"title": "理解 ElasticSearch 的倒排索引",
"content": "倒排索引把文档到词的关系反过来,变成词到文档的映射。",
"category": "elasticsearch",
"status": "published",
"author": "admin",
"views": 260,
"created_at": "2026-04-10"
}
POST article_search/_doc/3
{
"title": "Redis 缓存入门",
"content": "本文介绍 Redis 的字符串、哈希、列表和缓存使用场景。",
"category": "redis",
"status": "draft",
"author": "ops",
"views": 80,
"created_at": "2026-04-12"
}
POST article_search/_doc/4
{
"title": "ElasticSearch match 查询详解",
"content": "match 查询会分析查询文本,然后使用分析后的 term 去倒排索引中检索。",
"category": "elasticsearch",
"status": "published",
"author": "dev",
"views": 180,
"created_at": "2026-04-18"
}
刷新索引:
POST article_search/_refresh
三、Query DSL 是什么
ElasticSearch 的查询主要通过 JSON 表达,这套 JSON 查询语法通常叫 Query DSL。
最基本的搜索请求是:
POST article_search/_search
{
"query": {
"match_all": {}
}
}
其中:
POST article_search/_search:搜索article_search索引query:查询条件match_all:匹配全部文档
Query DSL 的好处是结构清晰,可以表达很复杂的查询条件,比如:
- 全文检索
- 精确匹配
- 范围过滤
- 多条件组合
- 排序
- 分页
- 高亮
- 聚合
1. _search 用 GET 还是 POST
ElasticSearch 的 _search API 同时支持 GET 和 POST。
例如:
GET article_search/_search
POST article_search/_search
不过只要查询条件放在 request body 中,更推荐统一使用 POST。
原因是:
- 查询 DSL 通常写在请求体里
- 有些 HTTP 客户端或代理对
GETbody 支持不一致 POST更符合提交复杂查询条件的使用习惯
所以本文后续示例统一使用:
POST article_search/_search
2. 搜索请求不只有 query
一个业务搜索请求中,除了 query,还经常会出现:
from/size:分页sort:排序_source:控制返回字段highlight:高亮aggs:聚合统计
例如:
POST article_search/_search
{
"from": 0,
"size": 10,
"_source": ["title", "category", "created_at"],
"query": {
"match": {
"content": "ElasticSearch"
}
},
"sort": [
{
"created_at": {
"order": "desc"
}
}
]
}
四、一个最简单的 match 查询
查询标题中包含 ElasticSearch 的文章:
POST article_search/_search
{
"query": {
"match": {
"title": "ElasticSearch"
}
}
}
match 是全文检索中最常用的查询。
它会做两件事:
- 先分析查询文本
- 再用分析后的 term 去倒排索引中查找
所以 match 适合查 text 字段,例如:
- 标题
- 正文
- 摘要
- 评论内容
五、查询结果怎么看
搜索结果里最常看的字段有这些:
{
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"hits": [
{
"_index": "article_search",
"_id": "1",
"_score": 0.8,
"_source": {
"title": "ElasticSearch 入门教程"
}
}
]
}
}
其中:
hits.total.value:命中文档数量hits.hits:具体命中的文档列表_score:相关性评分_source:原始文档内容
_score 越高,通常表示 ElasticSearch 认为这篇文档和查询越相关。
六、常见搜索类型概览
后面几篇会详细讲几类常用查询,这里先做一个总览。
1. match
match 是全文查询。
示例:
POST article_search/_search
{
"query": {
"match": {
"content": "倒排索引"
}
}
}
特点:
- 查询内容会被 analyzer 分析
- 适合
text字段 - 会计算相关性评分
- 是全文检索最常用的入口
适合:
- 搜标题
- 搜正文
- 搜文章内容
- 搜用户输入的关键词
2. match_phrase
match_phrase 是短语查询。
示例:
POST article_search/_search
{
"query": {
"match_phrase": {
"content": "倒排索引"
}
}
}
特点:
- 查询内容也会被分析
- 不只要求 term 命中,还要求位置关系符合短语顺序
- 比
match更严格
适合:
- 搜固定短语
- 搜连续词组
- 搜文章标题中的完整表达
3. term
term 是精确词项查询。
示例:
POST article_search/_search
{
"query": {
"term": {
"category": "elasticsearch"
}
}
}
特点:
- 查询值不会像
match那样走全文分析 - 直接拿给定 term 去倒排索引里找
- 最适合
keyword、数字、布尔、日期这类结构化字段
适合:
- 分类过滤
- 状态过滤
- 用户 ID
- 标签精确匹配
4. bool
bool 用来组合多个查询条件。
示例:
POST article_search/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"content": "ElasticSearch"
}
}
],
"filter": [
{
"term": {
"status": "published"
}
}
]
}
}
}
常见子句:
must:必须匹配,并参与评分should:应该匹配,可以提升评分filter:必须匹配,但不参与评分must_not:必须不匹配
适合:
- 多条件搜索
- 关键词 + 状态过滤
- 分类 + 时间范围 + 关键词组合
- 后台列表筛选
5. multi_match
multi_match 用来在多个字段中做全文检索。
例如同时搜索标题和正文:
POST article_search/_search
{
"query": {
"multi_match": {
"query": "ElasticSearch 搜索",
"fields": ["title", "content"]
}
}
}
它适合用户输入一个关键词,同时查标题、正文、摘要等多个字段的场景。
fields 里还可以给字段设置权重:
POST article_search/_search
{
"query": {
"multi_match": {
"query": "ElasticSearch 搜索",
"fields": ["title^3", "content"]
}
}
}
这里 title^3 表示标题命中比正文命中更重要。
multi_match 还有几种常见 type:
best_fields:哪个字段最匹配,主要看哪个字段most_fields:多个字段命中可以叠加cross_fields:把多个字段当成一个整体看phrase_prefix:适合短语前缀bool_prefix:适合搜索框输入中的联想式查询
6. range
range 用于范围查询。
例如查询浏览量大于 100 的文章:
POST article_search/_search
{
"query": {
"range": {
"views": {
"gt": 100
}
}
}
}
它适合数字范围、时间范围、价格范围等结构化条件。
7. exists
exists 用于判断字段是否存在。
POST article_search/_search
{
"query": {
"exists": {
"field": "created_at"
}
}
}
它适合筛选字段不为空的数据,也适合做数据质量排查。
七、全文查询和精确查询的区别
理解 ElasticSearch 查询时,最容易混淆的是 match 和 term。
可以先这样记:
match:先分析,再查询
term:不分析,直接查 term
例如 title 是 text 字段,写入:
ElasticSearch 入门教程
match 查询:
{
"match": {
"title": "ElasticSearch"
}
}
通常可以命中。
但如果用 term 查询 text 字段:
{
"term": {
"title": "ElasticSearch"
}
}
就可能因为大小写、分词结果不一致而查不到。
所以经验上:
- 搜正文、标题:优先
match - 查分类、状态、ID:优先
term - 查连续短语:使用
match_phrase - 多条件组合:使用
bool
精确搜索里还会见到一些特殊查询:
prefix:前缀匹配wildcard:通配符匹配regexp:正则匹配
这些查询很直观,但不要轻易作为普通搜索框的主力方案。尤其是前导通配、复杂通配和正则,在数据量大时可能带来明显性能压力。
八、总结
这一篇是搜索系列的入口。
先记住下面几条就够了:
- ElasticSearch 搜索主要用 Query DSL 表达
match适合全文检索match_phrase适合短语匹配term适合精确词项查询bool适合组合多个查询条件multi_match适合多字段全文检索range适合数字和时间范围exists适合判断字段是否存在text字段通常配合全文查询keyword字段通常配合精确查询和过滤
后面几篇会分别展开 match、match_phrase、term 和 bool。
参考链接
-
Query DSL
https://www.elastic.co/docs/query-languages/query-dsl -
Match query
https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-match-query -
Boolean query
https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-bool-query -
Search API
https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-search

更多推荐




所有评论(0)