- Published on
在 Elasticsearch (ES) 进行查询 | DSL
- Authors
- Name
- Shelton Ma
0. DSL
全文模糊搜索
POST /app-logs/_search { "query": { "match": { "message": "server error" } } }
精确搜索
POST /users/_search { "query": { "term": { "userId": "1234" } } }
范围查询 + 时间排序
POST /app-logs/_search { "query": { "range": { "timestamp": { "gte": "2024-01-01T00:00:00", "lte": "2024-12-31T23:59:59" } } }, "sort": [ { "timestamp": { "order": "desc" } } ], "size": 10 }
多条件组合查询(bool)
# 查找最近一天内,日志级别是 error 的记录 POST /app-logs/_search { "query": { "bool": { "must": [ { "match": { "level": "error" } }, { "range": { "timestamp": { "gte": "now-1d/d" } } } ] } } }
聚合统计(类似 SQL 的 COUNT + GROUP BY)
POST /app-logs/_search { "size": 0, "aggs": { "error_by_user": { "terms": { "field": "userId.keyword", "size": 5 } } } }
常用汇总
{
"query": {
"bool": {
"must": [...],
"filter": [...],
"should": [...],
"must_not": [...]
}
},
"sort": [...],
"from": 0,
"size": 10,
"aggs": {...}
}
1. 查询优化
使用
_source
控制返回字段默认查询返回整个_source 数据,如果字段很多,响应体会很大,影响性能. 可以用_source 控制返回字段
# 效果:只返回 user_id 和 message,减少数据传输,提高查询速度. GET logs-*/_search { "_source": ["user_id", "message"], "query": { "match": { "message": "error" } } }
使用
stored_fields
仅返回指定字段 如果字段 已存储,可以使用 stored_fields 提高查询效率:# 适用于 "_source": false 但存储了某些字段的情况. GET logs-*/_search { "stored_fields": ["user_id", "message"], "query": { "match": { "message": "error" } } }
使用
doc_values
提高排序/聚合性能默认情况下,字符串字段 (text) 不能用于排序,但 keyword 类型支持
GET logs-*/_search { "sort": [ { "timestamp": "desc" } ] }
优化方式
# 时间字段使用 date 类型 # 字符串字段使用 keyword 而非 text # 确保字段启用了 doc_values PUT logs-*/_mapping { "properties": { "timestamp": { "type": "date", "format": "epoch_millis" }, "user_id": { "type": "keyword", "doc_values": true } } }
避免 wildcard,使用 keyword 进行前缀搜索
wildcard 查询效率低,推荐使用 prefix
GET logs-*/_search { "query": { "prefix": { "user_id": "abc" } } }
或者使用 wildcard 但限制 keyword
GET logs-*/_search { "query": { "wildcard": { "user_id.keyword": "abc*" } } }
使用 filter 而不是 must(避免 score 计算)
使用 keyword 查询精确值
使用 exists 避免 null 检查
分页查询时,避免 deep pagination. 比如基于时间的查询
{ "size": 10, "query": { "match_all": {} }, "sort": [{ "timestamp": "desc" }], "search_after": [1689123456] }
使用 terms 批量查询多个值
{ "query": { "terms": { "status": ["active", "pending"] } } }
使用 aggregation 进行数据统计, 而不是 match_all + 手动遍历数据