在上一篇文章 “Elasticsearch:运用scroll接口对大量数据实现更好的分页”,我们讲述了如何运用scroll接口来对大量数据来进行有效地分页。在那篇文章中,我们讲述了两种方法:
- from加上size的方法来进行分页
- 运用scroll接口来进行分页
对于大量的数据而言,我们尽量避免使用from+size这种方法。这里的原因是index.max_result_window的默认值是10K,也就是说from+size的最大值是1万。搜索请求占用堆内存和时间与from+size成比例,这限制了内存。假如你想hit从990到1000,那么每个shard至少需要1000个文档:
为了避免过度使得我们的cluster繁忙,通常Scroll接口被推荐作为深层次的scrolling,但是因为维护scroll上下文也是非常昂贵的,所以这种方法不推荐作为实时用户请求。search_after参数通过提供实时cursor来解决此问题。 我们的想法是使用上一页的结果来帮助检索下一页。
我们先输入如下的文档到twitter索引中:
1 | POST _bulk |
这里共有6个文档。假设检索第一页的查询如下所示:
1 | GET twitter/_search |
显示的结果为:
1 | { |
上述请求的结果包括每个文档的sort值数组。 这些sort值可以与search_after参数一起使用,以开始返回在这个结果列表之后的任何文档。 例如,我们可以使用上一个文档的sort值并将其传递给search_after以检索下一页结果:
1 | GET twitter/_search |
在这里在search_after中,我们把上一个搜索结果的sort值放进来。 显示的结果为:
1 | { |
注意:当我们使用search_after时,from值必须设置为0或者-1。
search_after不是自由跳转到随机页面而是并行scroll多个查询的解决方案。 它与scroll API非常相似,但与它不同,search_after参数是无状态的,它始终针对最新版本的搜索器进行解析。 因此,排序顺序可能会在步行期间发生变化,具体取决于索引的更新和删除。