提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 方式一:from + size
- 实现原理
- 使用方式
- 优缺点
- 方式二:scroll
- 实现原理
- 使用方式
- 优缺点
- 方式三:search_after
- 实现原理
- 使用方式
- 优缺点
- 三种方式总结
方式一:from + size
- from + size是Elasticsearch中最直观的分页方式。其中,from参数表示从第几条记录开始返回,size参数表示返回的记录数。
实现原理
使用方式
- 在Elasticsearch中,使用from和size进行分页查询的DSL(Domain Specific Language):
GET /your_index/_search
{
"query": {
"match_all": {} // 这里可以替换为任何你需要的查询条件
},
"from": 0, // 从第几条记录开始,索引从0开始
"size": 10, // 返回的记录条数
"sort": [
{ "field_name": {"order": "asc"}} // 可选,根据某个字段进行排序
]
}
from参数指定了从哪一条记录开始返回,size参数指定了要返回的记录条数。
假设一个名为products的索引,搜索名称中包含"apple"的产品,并且从第10条记录开始返回10条结果,按价格升序排序:
GET /products/_search
{
"query": {
"match": {
"name": "apple"
}
},
"from": 9, // 注意,索引从0开始,所以第10条记录的索引是9
"size": 10,
"sort": [
{ "price": {"order": "asc"}}
]
}
from设置为9以跳过前9条记录,size设置为10以返回接下来的10条记录,并且结果按照price字段的升序排列。
Elasticsearch会返回如下响应:
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 100, // 假设总共有100条符合查询条件的产品
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "products",
"_type": "_doc", // 注意:在Elasticsearch 7.x及之后的版本中,_type字段通常被设置为"_doc"
"_id": "10",
"_score": 1.0,
"_source": {
"name": "Apple iPhone 12",
"price": 999.99,
// ... 其他字段
}
},
// ... 其他9条产品的结果
{
"_index": "products",
"_type": "_doc",
"_id": "19",
"_score": 1.0,
"_source": {
"name": "Apple Watch Series 6",
"price": 399.99,
// ... 其他字段
}
}
]
}
}
优缺点
使用场景
- 适用于数据量不大、实时性要求高的场景。
方式二:scroll
- scroll是一种基于游标的分页方式,它允许我们遍历大量数据而不需要在每次请求时重新计算整个搜索。
实现原理
使用方式
在Elasticsearch中,scroll是一种用于检索大量数据(可能是数百万条记录)的分页机制,它允许你保持一个搜索的“上下文”并继续检索结果,而不需要为每一页都重新计算整个搜索。以下是使用scroll进行分页的DSL代码示例:
DSL 代码示例
// 初始化scroll搜索
POST /_search/scroll
{
"size": 100, // 每次返回的文档数量
"scroll": "1m", // 保持scroll上下文的活动时间,这里是1分钟
"query": {
"match_all": {} // 可替换为任何需要的查询条件
}
}
// 后续的scroll请求(在第一次请求返回后)
POST /_search/scroll
{
"scroll": "1m", // 保持与第一次请求相同的scroll上下文时间
"scroll_id": "你的scroll_id" // 第一次请求返回的scroll_id
}
响应结果
第一次请求会返回如下结果:
{
"_scroll_id": "DnF1ZXJ5THV6QXRlbl84791547351",
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": {
"value": 1000,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "your_index",
"_type": "_doc",
"_id": "1",
"_score": 1.0,
"_source": {
// ... 文档的源数据 ...
}
},
// ... 其他文档 ...
]
}
}
- 响应中可以看到_scroll_id字段,这个值需要用于后续的scroll请求。
后续的scroll请求
使用上面响应中的_scroll_id进行后续的scroll请求:
POST /_search/scroll
{
"scroll": "1m",
"scroll_id": "DnF1ZXJ5THV6QXRlbl84791547351"
}
- 这个请求会返回下一批文档,直到所有的文档都被检索完或者scroll上下文过期。
- 根据你的Elasticsearch集群的实际设置和性能需求来调整size和scroll参数的值。
优缺点
方式三:search_after
- search_after是一种基于排序值的分页方式,它允许我们根据上一页的最后一条数据的排序值来获取下一页的数据。
实现原理
使用方式
GET /products/_search
{
"size": 10,
"query": {
"match_all": {} // 或者你可以添加具体的查询条件
},
"sort": [
{ "price": {"order": "desc"}},
{ "created_at": {"order": "asc"}}
]
}
{
"_index": "products",
"_type": "_doc",
"_id": "最后一个产品的ID",
"_score": null,
"_sort": [
129.99, // 最后一个产品的price值
"2023-10-23T12:00:00Z" // 最后一个产品的created_at值
],
"_source": {
// ... 产品的详细信息 ...
}
}
GET /products/_search
{
"size": 10,
"query": {
"match_all": {} // 保持与初始查询相同的查询条件
},
"sort": [
{ "price": {"order": "desc"}},
{ "created_at": {"order": "asc"}} // 保持与初始查询相同的排序字段和顺序
],
"search_after": [
129.99, // 上一页最后一个产品的price值
"2023-10-23T12:00:00Z" // 上一页最后一个产品的created_at值
]
}
优缺点
三种方式总结