Get查询:
get查询的特点
- 数据写入先存 IndexBuffer + Translog,此时 Get 可查、Search 不可查。
- 执行 Refresh 后,Buffer 数据生成 Segment 写入系统文件缓存。
- 只有落地到文件缓存、构建完倒排索引,Search 才能查询到。
- 自动刷新间隔默认 1s,因此 ES 查询是近实时。
两种查询方式:
GET citibike-202201/_doc/63AF72AB3CD47753?preference=_local&routing=afd&refresh=false&version=1&stored_fields=*&realtime=true
GET /citibike-202201/_mget
{
"docs":[
{
"_id":"63AF72AB3CD47753"
},
{
"_id":"63AF72AB3CD47753"
}
]
}
Search查询
allow_no_indices:
在使用通配符进行查询时,是否允许索引不存在,默认是不允许的
GET citibike-202201,index_test*/_search?allow_no_indices=true
from 和 size实现分页:
GET citibike-202201/_search?from=110&size=100
batched_reduce_size:
在使用通配符进行匹配时,防止因为查询分片过多,造成我们的es服务器出现问题,我们在查询时,可以设定一下最多的查询分片数,使用字段batched_reduce_size进行设置
GET citibike-202201*/_search?batched_reduce_size=10
search_type
1. query_then_fetch(默认)
- 流程(两阶段)
- 协调节点广播查询到所有相关分片;
- 各分片本地算分(只用自己分片的词频),返回「文档 ID + 分数」;
- 协调节点全局排序,取前
size个; - 再去对应分片批量拉取完整文档内容返回给客户端。
- 特点
- ✅ 快:只需 1 轮分片往返,算分用本地词频;
- ⚠️ 算分不准:不同分片词频独立,跨分片相关性对比有偏差Elastic。
- 适用:绝大多数场景(日志、监控、普通检索),追求速度优先Elastic。
2. dfs_query_then_fetch
- 流程(三阶段)
- 预查询(DFS):协调节点先问所有分片要「全局词频统计」;
- 全局算分 :用全分片合并后的全局词频,再广播查询;
- 后续同
query_then_fetch:分片返回 ID + 分数 → 协调节点排序 → 拉取文档。
track_total_hits
track_total_hits=true 用于强制 Elasticsearch 精确统计本次检索命中的全部文档总数,放弃默认的近似总数优化逻辑,以额外的性能开销为代价,返回完全准确的匹配数据总量。
GET citibike-202201*/_search?track_total_hits=true
sort
使用sort指定字段排序
GET page_study_index/_search?sort=number&from=10&size=100
scroll
scroll 是 Elasticsearch 用于高效批量获取大量数据的游标机制,核心作用是避免深分页导致的性能损耗,它会在服务端创建一个数据快照并保持搜索上下文,通过游标逐批读取数据,直到获取全部结果。使用时需要先发起带 scroll 参数的初始化搜索请求,指定上下文保留时间,请求会返回第一批数据和一个 _scroll_id 游标标识。后续所有数据读取都通过 _scroll API 提交该游标标识,无需重复执行查询条件,Elasticsearch 会基于之前的上下文持续返回下一批数据。每次请求都会沿用服务端的快照数据,保证数据一致性,不会受到索引实时写入、更新的影响。应用场景主要集中在全量数据导出、批量数据迁移、大数据量统计分析等需要获取上万甚至百万级文档的操作,替代 from+size 深分页方案。使用完成后必须主动清除 scroll 上下文释放服务端资源,避免占用内存造成性能影响,在实际开发中,它是处理海量非实时数据的标准方案,而普通的前端分页查询则不建议使用 scroll。
第一步:初始化 scroll
GET 你的索引名/_search?scroll=1m
{
"size": 100,
"query": {
"match_all": {}
}
}
scroll=1m:让 ES 保留搜索上下文 1 分钟size: 每一批返回多少条(比如 100)- 第一次执行后,会返回两个关键东西:
_scroll_id:游标 ID(很长一串字符串)- 第一批 100 条数据
第二步:循环滑动游标(取下一批数据)
POST _search/scroll
{
"scroll": "1m",
"scroll_id": "这里换成第一步返回的scroll_id"
}
含义
- 不需要再带索引名、查询条件
- 只需要传
scroll_id+ 保留时间 - 每次执行,都会返回下一批数据
- 一直执行,直到 hits 为空,代表读完了
第三步:用完必须删除游标(释放资源)
DELETE _search/scroll
{
"scroll_id": "你的游标ID"
}
含义
- scroll 会占用 ES 内存
- 不删会导致性能下降
- 读完数据必须清理
使用es进行格式转换:
通过下面的方式对于时间格式进行转换
GET citibike-202201/_search
{
"fields": [
{
"field": "started_at",
"format": "yyyy-mm-dd"
}
]
}
使用脚本的方式处理数据
GET citibike-202201/_search
{
"_source": ["*"],
"script_fields": {
"my_result": {
"script": {
"source": """
params._source.rideable_type + params._source.end_station_id;
"""
}
}
}
}
script_fields里面的数据只能用于结果展示用 → 不能排序、不能统计
runtime_mappings
runtime_mappings(运行时字段) :是「真・字段」,可以排序、可以聚合、可以过滤、可以查询,和普通字段用法几乎一样Elastic。
runtime_mappings = 运行时临时字段
- 只在当前这一次查询中生效
- 不会修改数据、不会写入磁盘、不会保存到索引里
- 查询结束就消失,下次查询要重新定义
GET citibike-202201/_search
{
"runtime_mappings": {
"runtime_text_name": {
"type": "keyword",
"script": {
"source": """
emit(params._source.rideable_type + params._source.end_station_id);
"""
}
}
},
"fields": ["runtime_text_name"], 加上这个才可以显示出来我们运行时计算的字段
"_source": false
}
异步方式
POST citibike-202201/_async_search?timeout=1ms
_pit查询:
我们在实际的查询过程中,因为数据的改变每次返回的数据可能是不一致的,但是如果我们在使用_pit进行查询时可以设置结果多久不会变。
下面的例子中展示了保证结果一分钟不改变
POST citibike-202201/_pit?keep_alive=1m
完整查询语句
http
POST /_search
{
"size": 10,
"query": {
"match_all": {}
},
"pit": {
"id": "把你刚才获取的PIT-ID粘贴在这里",
"keep_alive": "1m"
}
}
关键规则(必须遵守)
- 查询地址 :必须用
POST /_search,不能带索引名 - 必传参数 :
pit.id填你获取的 ID - 延长有效期 :
pit.keep_alive每次查询都会刷新快照有效期 - 结果一致性 :
- 1 分钟内,无论索引数据怎么变,查询结果完全一致
- 超时后 PIT 自动失效,无法再使用
完手动删除 PIT(推荐)
PIT 会占用内存,不用了可以手动删除:
DELETE /_pit
{
"id": "你的PIT-ID"
}