在'扫描&扫描过程中的Elasticsearch SearchContextMissingException滚动'使用Spring Data Elasticsearch进行查询

时间:2016-06-30 12:01:11

标签: java spring elasticsearch spring-data-elasticsearch

我正在使用带有默认群集配置的elasticsearch 2.2.0。我使用spring data elasticsearch遇到了扫描和滚动查询的问题。当我执行查询时,我得到这样的错误:

[2016-06-29 12:45:52,046][DEBUG][action.search.type       ] [Vector] [155597] Failed to execute query phase
RemoteTransportException[[Vector][10.132.47.95:9300][indices:data/read/search[phase/scan/scroll]]]; nested: SearchContextMissingException[No search context found for id [155597]];
Caused by: SearchContextMissingException[No search context found for id [155597]]
    at org.elasticsearch.search.SearchService.findContext(SearchService.java:611)
    at org.elasticsearch.search.SearchService.executeScan(SearchService.java:311)
    at org.elasticsearch.search.action.SearchServiceTransportAction$SearchScanScrollTransportHandler.messageReceived(SearchServiceTransportAction.java:433)
    at org.elasticsearch.search.action.SearchServiceTransportAction$SearchScanScrollTransportHandler.messageReceived(SearchServiceTransportAction.java:430)
    at org.elasticsearch.transport.TransportService$4.doRun(TransportService.java:350)
    at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

我的扫描&滚动'代码:

public List<T> getAllElements(SearchQuery searchQuery) {
    searchQuery.setPageable(new PageRequest(0, PAGE_SIZE));
    String scrollId = elasticsearchTemplate.scan(searchQuery, 1000, false);
    List<T> allElements = new LinkedList<>();
    boolean hasRecords = true;
    while (hasRecords) {
        Page<T> page = elasticsearchTemplate.scroll(scrollId, 5000, resultMapper);
        if (page.hasContent()) {
            allElements.addAll(page.getContent());
        } else {
            hasRecords = false;
        }
    }
    elasticsearchTemplate.clearScroll(scrollId);
    return allElements;
}

当我的查询结果大小小于PAGE_SIZE参数时,这样的错误会发生五次。我想这是每个碎片一个。当结果大小大于PAGE_SIZE时,错误会发生几次。我试图重构我的代码而不打电话:

Page<T> page = elasticsearchTemplate.scroll(scrollId, 5000, resultMapper);

当我确定该页面没有内容时。但它只有在PAGE_SIZE大于查询结果时才有效,因此根本不是解决方案。

我必须补充一点,它仅在弹性搜索方面存在问题。在客户端,错误被隐藏,并且在每种情况下查询结果都是正确的。有谁知道导致这个问题的原因是什么?

感谢您的帮助,

西蒙。

3 个答案:

答案 0 :(得分:3)

我遇到了类似的问题,我怀疑Spring Data Elasticsearch有一些关于传递Scroll-ID的内部错误。在我的情况下,我只是试图滚动整个索引,我可以排除@Val关于&#34的回答;如果您的搜索上下文不再存在,通常会发生这种情况&#34;,因为无论持续时间如何都会发生异常。此外,例外在第一页之后开始,并且每隔一个页面查询都会发生。

就我而言,我可以简单地使用elasticsearchTemplate.stream()。它使用Scroll&amp;内部扫描,似乎正确传递Scroll-ID。哦,它使用起来更简单:

SearchQuery searchQuery = new NativeSearchQueryBuilder()
    .withQuery(QueryBuilders.matchAllQuery())
    .withPageable(new PageRequest(0, 10000))
    .build();

Iterator<Post> postIterator = elasticsearchTemplate.stream(searchQuery, Post.class);

while(postIterator.hasNext()) {
    Post post = postIterator.next();
}

答案 1 :(得分:2)

如果ElasticSearch系统关闭连接,我会收到此错误。通常它正是@Val所说的 - 死连接。事情有时会在ES中消失,没有充分理由 - 主节点关闭,数据节点过于拥挤,执行不良查询,Kibana在查询中间同时运行...我被所有这些都击中了时间或其他时间来获得此错误。

建议:初始连接时间 - 1000L可能太短,无法获得所需的内容。如果查询越早结束,它就不会受到伤害。

当我尝试快速提取过多数据时,这也会随机发生;你可能有大量的文件,并试图拉动50,000的PAGESIZE可能有点太多了。我们不知道您为PAGESIZE选择了什么。

建议:将PAGESIZE降低到500以下。或者20.看看这些较小的值是否会减慢错误。

我知道迁移到ES 2.3.3之后我遇到的问题就更少了。

答案 2 :(得分:1)

如果您的搜索环境不再存在,通常会发生这种情况。

在您的情况下,您以1秒的超时开始扫描,然后每次扫描在5秒内仍然存在。它可能太低了。使搜索上下文保持活动状态的default duration是1分钟,所以你应该把它增加到60秒,如下所示:

String scrollId = elasticsearchTemplate.scan(searchQuery, 60000, false);
...
Page<T> page = elasticsearchTemplate.scroll(scrollId, 60000, resultMapper);