ElasticSearch使用Scroll检索大规模数据
目录
本文属于介绍 NWPC 消息平台 系列文章。
默认配置下 ElasticSearch 单个查询只能返回一页 (page) 数据,默认一页大小为 10000。 想要检索大规模数据,有多种方式。 本文介绍使用 scroll API 获取大规模数据的方法。
标准查询
查询 2020 年 12 月 GRAPES TYM 系统的所有产品消息。 TYM 系统一天运行 4 次,每个时次生成 121 个产品,理论上 12 月一共有 4 * 121 * 31 = 15004 个消息。
请求 API
POST /2020-12/_search
请求体
{
"query": {
"term" : {
"data.system": "grapes_tym"
}
},
"sort": {
"time": "asc"
}
}
查询结果如下 (省略返回条目)。 可以看到只查询到 10000 个结果。
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 10000,
"relation" : "gte"
},
"max_score" : null,
"hits" : [
"...skip..."
]
}
}
Scroll 查询
ElasticSearch 提供 Scroll API 支持使用单个查询返回大量数据,甚至可以返回数据全集, 类似关系型数据库中的 curser。
请求 API 中指定 scroll
参数,告知 ElasticSearch 服务器保存当前查询内容 (search context) 的持续时间。
下面的请求中 1m
表示保存 1 分钟。
POST /2020-12/_search?scroll=1m
请求体与标准查询相同
{
"query": {
"term" : {
"data.system": "grapes_tym"
}
},
"sort": {
"time": "asc"
}
}
返回结果显示检索找到 15003 个数据。
注:因为数据按消息生成时间字段 time
分布在不同索引中,查询得到的总数据量可能比理论数据量少。
返回结果中的 _scroll_id
字段表示当前查询的 ID 号,使用该 ID 号可以继续获取该查询的文档。
{
"_scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFGlsT2YwSFlCUGp5MzZGa0xWa3FuAAAAAAAxr0MWZk9kZ3V3Q0NUYTZEYU5zY0kwWF9YUQ==",
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 15003,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
"...skip..."
]
}
}
使用 scroll_id
再次获取前面查询的文档
POST /_search/scroll
查询体
{
"scroll" : "1m",
"scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFGlsT2YwSFlCUGp5MzZGa0xWa3FuAAAAAAAxr0MWZk9kZ3V3Q0NUYTZEYU5zY0kwWF9YUQ"
}
返回结果与前次查询类似
{
"_scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFGlsT2YwSFlCUGp5MzZGa0xWa3FuAAAAAAAxr0MWZk9kZ3V3Q0NUYTZEYU5zY0kwWF9YUQ",
"took" : 7,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 15003,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
"...skip..."
]
}
}
多次执行该步骤,可以获取查询对应的所有文档。
实现
本节介绍如何在 elasticsearch-py 中使用 scroll API。
创建 SCROLL API 查询
result = client.search(
index="2020-12",
body={
"query": {
"term" : {
"data.system": "grapes_tym"
}
},
"sort": {
"time": "asc"
}
},
scroll="1m",
)
从返回结果中获取 scroll_id
scroll_id = result["_scroll_id"]
继续当前查询
result = client.scroll(
scroll="1m",
scroll_id=scroll_id
)
参考
官方文档:
项目示例: