在项目中我用到ES的两种分页方式,这里记录一下。
Pageable深度分页
GET my_index/_search
{
"size": 10, // 每页数量
"from": 0, // 第几页
"query": {
"match_all": {}
}
}
Spring data实现
接口接收Map
对象和spring pageable
,StringQuery
载入检索条件和分页参数,使用ElasticsearchRestTemplate
进行检索。
@PostMapping("/_search")
fun search(@RequestBody body: Map<String, Any>, pageable: Pageable): Mono<SearchHits<Any>> {
val json = Gson().toJson(body)
val query = StringQuery(json)
query.setPageable<StringQuery>(pageable)
return mono {
esTemplate.search(query, Any::class.java)
}
}
Scroll游标分页
GET my_index/_search?scroll=1m
{
"size": 100,
"query": {
"match_all": {}
}
}
1m
表示scroll_id
在一分钟内有效。
返回结果
{
"_scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAA3j8YWNXNZY212SFJRd0N3bUlzU1paSVVnZw==",
"took" : 23,
\\ 以下省略几百行
}
使用返回结果中的_scroll_id
进行下次搜索。
GET _search/scroll
{"scroll":"1m","scroll_id":"DXF1ZXJ5QW5kRmV0Y2gBAAAAAAA3gekWNXNZY212SFJRd0N3bUlzU1paSVVnZw=="}
Spring data实现
// 首次进行搜索
@PostMapping("/_search")
fun searchStart(@RequestBody body: Map<String, Any>): Mono<SearchHits<Any>> {
val json = Gson().toJson(body)
val query = StringQuery(json)
query.setMaxResults(100)
return mono {
esTemplate..searchScrollStart(
Duration.ofMinutes(5).toMillis(),
query,
Any::class.java,
IndexCoordinates.of("my_index")
)
}
}
// 再次搜索
@GetMapping("/_search/{scrollId}")
fun continueSearch(@PathVariable scrollId: String): Mono<SearchHits<Any>> {
return mono {
esTemplate..searchScrollContinue(
scrollId,
Duration.ofMinutes(5).toMillis(),
Any::class.java,
IndexCoordinates.of("my_index")
)
}
}
需要注意:
-
Duration
是scroll_id
的有效时间 - scroll搜索不能使用分页参数,只能设置最大返回结果数量
setMaxResults
,因为from
参数已被删除。若使用pageable
则会报以下错误,官网给出的解释。
Validation Failed: 1: using [from] is not allowed in a scroll context;
网友评论