Elasticsearch 常用 DSL 语句(速查表)原创
版本说明
本文是速查表,不含原理推导,仅列出可直接粘贴执行的 DSL 语句。适用 Elasticsearch 7.x/8.x,经 2026-09 复核,语法未变。
如需了解 Query/Filter 缓存差异、match 与 term 的选择原理,详见 Elasticsearch 字符串搜索方式。
# Query vs Filter 速记
| 场景 | 使用 | 原因 |
|---|---|---|
| 需要算分(_score) | query | 会计算相关性 |
| 仅需过滤(yes/no) | filter | 不计算算分,可缓存,性能更好 |
# 1. 基本查询(Match Query)
{
"query": {
"match": {
"title": "Elasticsearch"
}
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- 对
text类型字段会先分词,再查 inverted index - 对
keyword类型字段等同于 term 查询
常见错法 → 正确写法
| 错法 | 问题 | 正确写法 |
|---|---|---|
match: {status: "active"} 查 keyword 字段期望精确匹配 | 语义正确但写法冗余 | term: {status: "active"} 更清晰 |
match: {ip: "<IP>"} 查 IP 字符串 | 被分词成多个 token | term: {ip: "<IP>"} |
# 2. 多字段匹配(Multi-Match Query)
{
"query": {
"multi_match": {
"query": "search term",
"fields": ["title^2", "description"]
}
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- 同时在多个字段中查询
^2表示 title 字段权重加倍
常见错法 → 正确写法
| 错法 | 问题 | 正确写法 |
|---|---|---|
fields: ["*"] 查询所有字段 | 性能差,会扫描 mapping 中所有字段 | 明确列出需要的字段 |
fields: ["title", "title.keyword"] | 重复查询同一字段 | 根据需求选 title(match)或 title.keyword(term) |
# 3. 精确匹配(Term Query)
{
"query": {
"term": {
"status": "active"
}
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- 不分词,直接查倒排索引
- ⚠️ 对
text字段使用可能无法匹配(text 被分词存储)
常见错法 → 正确写法
| 错法 | 问题 | 正确写法 |
|---|---|---|
term: {title: "Quick Brown"} 查 text 字段 | 存储时被分词成 quick/brown,原词无法匹配 | match_phrase: {title: "Quick Brown"} |
term: {status: "ACTIVE"} | term 区分大小写,原字段为小写 active | 用 terms 或确保大小写一致 |
# 4. 布尔组合(Bool Query)
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Elasticsearch" } }
],
"filter": [
{ "term": { "status": "published" } },
{ "range": { "publish_date": { "gte": "2024-01-01" } } }
],
"must_not": [
{ "term": { "hidden": true } }
],
"should": [
{ "match": { "tag": "featured" } }
]
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| 子句 | 功能 | 参与算分 | 可缓存 |
|---|---|---|---|
must | 必须匹配 | 是 | 否 |
filter | 必须匹配 | 否 | 是 |
must_not | 必须排除 | 否 | 是 |
should | 建议匹配(默认 OR) | 是 | 否 |
常见错法 → 正确写法
| 错法 | 问题 | 正确写法 |
|---|---|---|
把过滤条件放 must 而不是 filter | 白白计算算分,无法缓存 | 纯过滤条件放 filter 子句 |
should 只有一个条件且期望必须满足 | 单 should 不影响 must 逻辑 | 加 minimum_should_match: 1 |
# 5. 范围查询(Range Query)
{
"query": {
"range": {
"price": {
"gte": 10,
"lte": 100
}
}
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
gte= greater than or equal,lte= less than or equal- 也可用于日期:
"gte": "now-7d"
# 6. 短语匹配(Match Phrase Query)
{
"query": {
"match_phrase": {
"title": {
"query": "quick brown fox",
"slop": 1
}
}
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- 保持词序和邻近性
slop:允许词语间最大间隔(默认 0)
# 7. 存在性查询(Exists Query)
{
"query": {
"exists": {
"field": "tags"
}
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- 查询指定字段有可索引值的文档
- 字段值为
null、空数组[]、或未配置null_value的null时不命中 - 若 mapping 配置了
null_value: "NULL_STRING",写入的null会被替换成该值,反而会命中
反向查询(字段不存在)
{
"query": {
"bool": {
"must_not": [
{ "exists": { "field": "deleted_at" } }
]
}
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 8. ID 批量查询(IDs Query)
{
"query": {
"ids": {
"values": ["1", "2", "3", "100"]
}
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- 按
_id批量查询,比多次GET /index/_doc/id更高效 - 跨索引查询写在 URL 上:
GET /index1,index2/_search,ids 本身不支持跨索引 type参数在 7.x 已废弃、8.x 已移除,曾指 mapping type 而非索引名
# 9. 多词精确匹配(Terms Query)
{
"query": {
"terms": {
"status": ["active", "pending", "reviewing"]
}
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
- 字段值在列表中的文档(OR 关系)
- 不分词,直接匹配倒排索引
# 10. 模糊匹配最小词数(Terms Set Query)
{
"query": {
"terms_set": {
"skills": {
"terms": ["java", "python", "elasticsearch"],
"minimum_should_match_field": "required_matches"
}
}
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- 指定字段至少匹配 N 个词,N 来自文档中的另一个字段
- 适合"技能匹配至少 2 项"这类需求
固定数值版本(8.x+)
8.x 可直接用 minimum_should_match 整数参数:
{
"query": {
"terms_set": {
"skills": {
"terms": ["java", "python", "elasticsearch"],
"minimum_should_match": 2
}
}
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
7.x 写法(用 script):
{
"query": {
"terms_set": {
"skills": {
"terms": ["java", "python", "elasticsearch"],
"minimum_should_match_script": {
"source": "params.num_terms >= 2"
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 11. 函数评分(Function Score Query)
{
"query": {
"function_score": {
"query": { "match": { "title": "elasticsearch" } },
"functions": [
{
"filter": { "term": { "featured": true } },
"weight": 2
},
{
"field_value_factor": {
"field": "popularity",
"factor": 1.2,
"modifier": "log1p"
}
},
{
"gauss": {
"publish_date": {
"origin": "now",
"scale": "30d",
"decay": 0.5
}
}
}
],
"score_mode": "sum",
"boost_mode": "multiply"
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
weight:固定权重加成field_value_factor:字段值影响评分(如按点击量排序)gauss/linear/exp:距离衰减(如按发布时间衰减)score_mode:多个函数间的计算方式(sum/multiply/avg/max/min/first)boost_mode:函数分与原始 query 分的组合方式
# 12. 排序(Sort)
{
"sort": [
{ "created_at": "desc" },
{ "_score": "desc" },
{ "price": { "order": "asc", "mode": "avg" } }
]
}
1
2
3
4
5
6
7
2
3
4
5
6
7
| 参数 | 说明 |
|---|---|
order | asc 升序 / desc 降序 |
mode | 多值字段的排序方式:min/max/sum/avg/median |
missing | 缺失值的排序位置:_last/_first 或具体值 |
unmapped_type | 字段不存在时的处理类型 |
按地理距离排序
{
"sort": [
{
"_geo_distance": {
"location": { "lat": 39.9, "lon": 116.4 },
"order": "asc",
"unit": "km"
}
}
]
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 13. 分页查询(From/Size vs Search After)
# 13.1 From + Size(浅分页)
{
"from": 100,
"size": 20,
"query": { "match_all": {} }
}
1
2
3
4
5
2
3
4
5
from:跳过的文档数size:返回的文档数- ⚠️
from + size默认上限 10000,超过报错
# 13.2 Search After(深分页)
{
"size": 20,
"query": { "match_all": {} },
"sort": [
{ "created_at": "desc" },
{ "_id": "asc" }
],
"search_after": [1690876800000, "doc_12345"]
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
- 上一页最后一条结果的 sort 值作为
search_after参数 - 需要指定唯一的排序字段组合(通常加
_id) - 无深度限制,但只能向前翻页
常见错法 → 正确写法
| 错法 | 问题 | 正确写法 |
|---|---|---|
from: 100000, size: 10 | 超出 10000 限制,直接报错 | 改用 search_after |
search_after 缺少 _id | 排序值重复时结果不稳定 | 最后加 { "_id": "asc" } 确保唯一 |
# 14. 字段投影与过滤(_source & fields)
# 14.1 _source 过滤
{
"_source": ["title", "author", "created_at"],
"query": { "match_all": {} }
}
1
2
3
4
2
3
4
排除特定字段
{
"_source": {
"includes": ["title", "author.*"],
"excludes": ["author.password", "internal_*"]
},
"query": { "match_all": {} }
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 14.2 fields 参数(7.10+ 推荐)
{
"fields": ["title", "created_at", "tags"],
"_source": false,
"query": { "match_all": {} }
}
1
2
3
4
5
2
3
4
5
- 返回字段的格式化值(如日期格式化、多字段类型选择)
- 支持通配符:
"fields": ["title.*", "meta.*"]
# 14.3 docvalue_fields(列存字段)
{
"docvalue_fields": ["status", "price"],
"query": { "match_all": {} }
}
1
2
3
4
2
3
4
- 从 doc values 读取,比
_source更高效 - 适合聚合或排序字段的返回
# 15. 聚合查询(Aggregation)
# 15.1 分桶聚合 Terms
{
"size": 0,
"aggs": {
"by_category": {
"terms": {
"field": "category",
"size": 100,
"min_doc_count": 10,
"order": { "_count": "desc" }
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
| 参数 | 说明 |
|---|---|
size | 返回桶的数量(默认 10) |
min_doc_count | 最少文档数才返回该桶 |
order | 桶的排序方式:_count、_key、子聚合名 |
子聚合示例
{
"size": 0,
"aggs": {
"by_category": {
"terms": { "field": "category" },
"aggs": {
"avg_price": { "avg": { "field": "price" } },
"max_price": { "max": { "field": "price" } }
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 15.2 时间直方图 Date Histogram
{
"size": 0,
"aggs": {
"by_month": {
"date_histogram": {
"field": "created_at",
"calendar_interval": "month",
"format": "yyyy-MM",
"min_doc_count": 1
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
| 参数 | 说明 |
|---|---|
calendar_interval | minute/hour/day/week/month/quarter/year |
fixed_interval | 固定时长如 30d、1h(不推荐与日历混用) |
format | 返回的日期格式 |
extended_bounds | 强制返回的最小/最大边界 |
# 15.3 基数去重 Cardinality
{
"size": 0,
"aggs": {
"unique_visitors": {
"cardinality": {
"field": "user_id",
"precision_threshold": 40000
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
| 参数 | 说明 |
|---|---|
precision_threshold | 精度阈值(默认 3000),最大支持 40000,内存换精度 |
| 错误率在阈值内约 1.5% |
# 16. 嵌套查询(Nested Query)
{
"query": {
"nested": {
"path": "comments",
"query": {
"bool": {
"must": [
{ "match": { "comments.author": "john" } },
{ "match": { "comments.text": "great" } }
]
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 用于
type: nested字段 - 保证子对象内部条件匹配同一数组元素
# 17. 前缀/通配符/正则
// 前缀(适合 autocomplete)
{ "query": { "prefix": { "username": "john" } } }
// 通配符(? 单字符,* 多字符,性能差)
{ "query": { "wildcard": { "username": "john*" } } }
// 正则(性能最差,慎用)
{ "query": { "regexp": { "username": "jo.*" } } }
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
⚠️ wildcard/regexp 扫描量大,仅适用于小数据量或已预过滤后的子集
# 18. 高亮查询
{
"query": {
"match": { "content": "Elasticsearch" }
},
"highlight": {
"fields": {
"content": {
"pre_tags": ["<em>"],
"post_tags": ["</em>"],
"fragment_size": 150,
"number_of_fragments": 3
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| 参数 | 说明 |
|---|---|
fragment_size | 高亮片段长度 |
number_of_fragments | 返回片段数,0 表示返回整个字段 |
# 常见限制速记
| 查询/聚合 | 默认限制 | 调整方式 |
|---|---|---|
terms 聚合桶数 | 10 | size: N |
from + size 深分页 | 10000 | 改用 search_after |
| 总命中数 | 10000 | track_total_hits: true |
search.max_buckets | 10000 | 集群配置 |
# Agent 可直接解析的元数据块
{
"runbook": {
"task": "elasticsearch-dsl-cheatsheet",
"permalinks": ["/pages/elasticsearch-dsl/"],
"category": "database/elasticsearch",
"tags": ["dsl", "query", "cheatsheet"],
"es_versions": ["7.x", "8.x"],
"verified_date": "2026-09"
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
上次更新: 9/3/2026