我正在使用Elastic Search通过我的java程序中的查询集对索引运行分页搜索。在这里,我有两个案例如下所述:
使用ES Scroll进行搜索。
这里例如:总搜索结果是10 010,页面大小是100.因此搜索结果将被分成11页,每页有100条记录。当我在每页上查看我的结果直到第10页时,正确地返回记录,即前10 000条记录。但是当我查看第11页,即从10 001到10 010的记录时,我得到以下错误:
RemoteTransportException [[James Jaspers] [127.0.0.1:9300] [indices:data / read / search [phase / query + fetch]]];嵌套:QueryPhaseExecutionException [结果窗口太大,+大小必须小于或等于:[10000]但是[10010]。
来设置此限制
引发者:QueryPhaseExecutionException [结果窗口太大,+大小必须小于或等于:[10000]但是[10010]。有关请求大型数据集的更有效方法,请参阅scroll api。可以通过更改[index.max_result_window]索引级别参数
以下是代码段,在此搜索页面中,值传递为100,DEFAULT_SEARCH_PAGE_SIZE为1000
if (searchPage != null) {
builder.setFrom((int) searchPage.getPageStart());
builder.setSize((int) searchPage.getPageSize());
} else {
builder.setFrom(0);
builder.setSize(DEFAULT_SEARCH_PAGE_SIZE);
}
builder.setTypes(getType());
SearchResponse response = builder.execute().actionGet(60000);
SearchHits hits = response.getHits();
if (hits.getTotalHits() > 0) {
for (SearchHit hit : response.getHits()) {
//process my hits and add them to list
}
}
//return the list
正如上面的错误所示,我尝试在下面的代码中使用弹性搜索中的Scroll,当我这样做时,上面的错误没有生成,但每页上返回的结果是相同的,即在每个页面上显示前100条记录。
if (searchPage != null) {
builder.setFrom((int) searchPage.getPageStart());
builder.setSize((int) searchPage.getPageSize());
} else {
builder.setFrom(0);
builder.setSize(DEFAULT_SEARCH_PAGE_SIZE);
}
builder.setTypes(getType()).setScroll(new TimeValue(60000));
SearchResponse response = builder.execute().actionGet(60000);
SearchHits hits = response.getHits();
if (hits.getTotalHits() > 0) {
for (SearchHit hit : response.getHits()) {
//process my hits and add them to list
}
}
//return the result
我知道在使用Elastic Search Scroll API时会有请求scrollId来获取我的下一个结果集,并且在使用之后,当我在我的搜索中顺序移动时,我可以在每个页面上得到正确的结果,即1,2,3, 4..etc。但是我还想直接跳到某个页面上,例如:我在第1页,想要继续第5页,然后Scroll Api将如何处理这个?
更新阻止
正如adityasinghraghav
解释
虽然您只请求数百个(在您的情况下仅存在10个)结果,即。从10000-10010引擎盖下弹性搜索必须得到所有10010结果排序然后丢弃10000结果
我已阅读有关max_result_window参数的信息。此参数默认为10,000,这对几乎所有群集都是安全的。 高于每个搜索和每个执行搜索的分片会占用大量堆内存的值。最安全的是保留此值,但此设置是动态的,因此可以根据需要升高或降低。
如果我的总结果= 500 000且我设置了最大结果Windows大小= 100 000且页面大小= 1000。
如果我想申请第5页,那么:
OR
答案 0 :(得分:2)
这是因为elasticsearch的最大结果窗口大小默认为10000。现在,虽然您只请求数百(在您的情况下只存在10)结果,即。从10000-10010引擎盖下弹性搜索必须得到所有10010结果排序它们然后丢弃10000结果然后给你10左,因此超过最大窗口大小的问题。 你可以做的最简单的事情是将这个默认值10000增加到一个非常高的值。您可以使用以下命令执行此操作:
curl -XPUT http://1.2.3.4:9200/index/_settings -d '{ "index" : { "max_result_window" : 1000000}}'
来到滚动api,它不返回分页结果,因此from
的概念不存在,size
参数以不同的方式使用。
滚动API将询问每个分片是否为其提供顶部" size
"结果如果size
为10并且您有5个主分片,则elasticsearch将返回50个结果。
现在,对滚动API的每个请求都会生成一个滚动ID,您需要将其传递给下一个查询以获取下一个"页面"结果而且,既然你没有这样做,你会得到相同的结果。
您应该阅读有关scroll api here的实现的更多信息。
但是我还想直接跳到某个页面上,例如:我在第1页,想要继续第5页
此外,由于滚动API中没有分页,因此您无法在非连续页面之间跳转。
现在您还必须记住,滚动弹性搜索会在索引时获取快照,因此如果您在滚动上下文打开期间对索引进行任何更改,这些更改将赢得&#39 ;反映在结果中。
答案 1 :(得分:0)
我不建议增加max_result_window。限制是有原因的,我认为我们应该避免篡改它。
让我们举一个例子,你运行一个通配符查询返回超过2000万个匹配(我在我的数据中看到,我们的索引有超过10亿条记录,主存储大小超过5 TB),用户要求最后一页是20万条记录。增加结果窗口将避免异常但会尝试加载堆中的所有2000万条记录,这将导致Out Of Memory崩溃整个服务器,我想这将非常糟糕。
如果滚动不是一个选项,我建议你应该使用Search After(https://www.elastic.co/guide/en/elasticsearch/reference/5.1/search-request-search-after.html)。但是Search after有其自身的局限性,应予以考虑。