mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
909 words
2 minutes
Elasticsearch 从 0 到 1(三):DSL 查询入门
2025-07-04

Elasticsearch 从 0 到 1(三):DSL 查询入门#

前两篇讲了 ES 的定位和索引建模:

这一篇开始写查询。

ES 查询使用 Query DSL,本质上是用 JSON 描述查询条件。

比如商品搜索:

关键词:蓝牙耳机
分类:数码耳机
价格:100-300
排序:销量优先
分页:第 1 页,每页 10 条

对应到 DSL,就是把这些条件组合起来。

match:全文搜索#

match 用于全文搜索,适合查 text 字段。

GET /products/_search
{
"query": {
"match": {
"title": "蓝牙耳机"
}
}
}

如果 titletext 字段,查询词会走分词器。

适合场景:

  • 商品标题搜索;
  • 文章内容搜索;
  • 描述字段搜索。

term:精确匹配#

term 用于精确匹配,适合查 keyword、数字、布尔等字段。

GET /products/_search
{
"query": {
"term": {
"brand": "SoundGo"
}
}
}

不要拿 term 直接查一个会分词的 text 字段,否则结果可能不符合预期。

简单记:

match:用于全文搜索
term:用于精确匹配

range:范围查询#

范围查询常用于价格、时间、销量。

GET /products/_search
{
"query": {
"range": {
"price": {
"gte": 100,
"lte": 300
}
}
}
}

常见操作符:

操作符含义
gt大于
gte大于等于
lt小于
lte小于等于

bool:组合查询#

真实业务里很少只有一个条件,更多是多个条件组合。

这时用 bool

GET /products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "蓝牙耳机" } }
],
"filter": [
{ "term": { "category": "数码耳机" } },
{ "range": { "price": { "gte": 100, "lte": 300 } } }
]
}
}
}

常见子句:

子句含义
must必须匹配,会影响相关性评分
filter必须匹配,不参与评分,适合过滤
should可选匹配,常用于提升相关性
must_not必须不匹配

业务里常用组合:

关键词搜索放 must
分类、品牌、价格范围放 filter
排除条件放 must_not

query context 和 filter context#

ES 查询里有两个重要概念:

  • query context:关心是否匹配,也关心匹配得多好;
  • filter context:只关心是否匹配,不计算相关性。

比如关键词搜索“蓝牙耳机”,不同商品相关性不同,需要评分。

但分类等于“数码耳机”、价格在 100 到 300,这类条件只是过滤,不需要评分。

所以商品搜索里通常这样分:

关键词:must
筛选条件:filter

排序#

按销量倒序:

GET /products/_search
{
"query": {
"match": {
"title": "蓝牙耳机"
}
},
"sort": [
{ "sales": "desc" }
]
}

按价格升序:

"sort": [
{ "price": "asc" }
]

如果没有显式排序,ES 默认会按 _score 相关性排序。

分页#

普通分页使用 fromsize

GET /products/_search
{
"from": 0,
"size": 10,
"query": {
"match": {
"title": "蓝牙耳机"
}
}
}

第 1 页:

from = 0
size = 10

第 2 页:

from = 10
size = 10

注意:深分页会越来越慢。

比如 from = 100000, size = 10,ES 需要在各分片上取出很多数据再合并排序。

深分页通常要考虑 search_after,生产优化放到第六篇讲:

Elasticsearch 从 0 到 1(六):性能优化与生产环境注意事项

高亮#

搜索结果里常见的关键词标红,就是高亮。

GET /products/_search
{
"query": {
"match": {
"title": "蓝牙耳机"
}
},
"highlight": {
"fields": {
"title": {}
},
"pre_tags": ["<em>"],
"post_tags": ["</em>"]
}
}

返回结果里会有 highlight 字段。

前端展示时可以优先使用高亮标题。

聚合查询#

聚合用于统计分析。

比如按品牌统计商品数量:

GET /products/_search
{
"size": 0,
"aggs": {
"brand_count": {
"terms": {
"field": "brand"
}
}
}
}

按价格区间统计:

GET /products/_search
{
"size": 0,
"aggs": {
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 100 },
{ "from": 100, "to": 300 },
{ "from": 300 }
]
}
}
}
}

商品搜索页左侧的品牌、分类、价格区间筛选,就可以用聚合来做。

一个完整商品搜索示例#

GET /products/_search
{
"from": 0,
"size": 10,
"query": {
"bool": {
"must": [
{ "match": { "title": "蓝牙耳机" } }
],
"filter": [
{ "term": { "category": "数码耳机" } },
{ "term": { "status": "ON_SALE" } },
{ "range": { "price": { "gte": 100, "lte": 300 } } }
]
}
},
"sort": [
{ "sales": "desc" },
{ "price": "asc" }
],
"highlight": {
"fields": {
"title": {}
}
}
}

这个查询已经接近真实商品搜索接口了。

这一篇先记住什么#

  • match 用于全文搜索;
  • term 用于精确匹配;
  • range 用于范围查询;
  • bool 用于组合条件;
  • must 会影响评分,filter 更适合筛选条件;
  • from + size 可以分页,但深分页要小心;
  • 高亮用 highlight
  • 聚合用 aggs,适合统计品牌、分类、价格区间。

下一篇把这些 DSL 接到 Spring Boot 项目里:

Elasticsearch 从 0 到 1(四):Spring Boot 集成与商品搜索实战

参考#

Share

If this article helped you, please share it with others!

Elasticsearch 从 0 到 1(三):DSL 查询入门
https://mizuki.mysqil.com/posts/elasticsearch-03-query-dsl/
Author
梦幻晨风
Published at
2025-07-04
License
CC BY-NC-SA 4.0

Some information may be outdated

Table of Contents