【问题标题】:Elasticsearch Search Scroll API doesn't retrieve all the documents from an indexElasticsearch Search Scroll API 不会从索引中检索所有文档
【发布时间】:2020-03-25 07:45:52
【问题描述】:

我想从 Elasticsearch 中检索所有文档,所以我参考了Search Scroll API

但我的问题是,它没有返回所有文档,我在一个索引中有 36 个文档,因为它只返回 26 个。

即使我检查了另一个索引,我有超过 10k 个文档,它也没有返回最后 10 个文档。

我真的不知道为什么它会这样返回它!任何帮助将不胜感激!提前致谢!

在我尝试过的代码下方:

final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L));
SearchRequest searchRequest = new SearchRequest("myindex");
searchRequest.scroll(scroll);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query("")//here some query;
searchRequest.source(searchSourceBuilder);

SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); 
String scrollId = searchResponse.getScrollId();
SearchHit[] searchHits = searchResponse.getHits().getHits();

while (searchHits != null && searchHits.length > 0) { 
    
    SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId); 
    scrollRequest.scroll(scroll);
    searchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT);
    scrollId = searchResponse.getScrollId();
    searchHits = searchResponse.getHits().getHits();
    for (SearchHits hit: searchHits){
       String source=hit.getSourceAsString();
    }
}

ClearScrollRequest clearScrollRequest = new ClearScrollRequest(); 
clearScrollRequest.addScrollId(scrollId);
ClearScrollResponse clearScrollResponse = client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
boolean succeeded = clearScrollResponse.isSucceeded();

【问题讨论】:

  • 您是在做一个或多个请求吗? Scroll API 不会在一个请求中返回所有文档,而是您在第一个请求中使用滚动参数初始化上下文,然后在此之后执行后续请求,并传递接收到的标识您的上下文的滚动 ID。您将分批获得所有这些请求的所有结果。
  • @Zsolt 我按照上面提到的链接代码,如果我错过了什么,请看一下??
  • 您能否在问题中包含一个代码 sn-p 以显示您如何处理请求?没有它就很难说缺少了什么。您需要循环执行请求以获取所有结果,如您引用的页面末尾的“完整示例”所示。
  • @Zsolt 是的,我提到了完整的例子
  • 我假设您删除了一些代码,看起来您正在处理 while 循环结束时的结果,对吗?请注意,当您在循环之前执行第一个请求时,它也应该返回一组结果,您也处理吗?如果不是,那可能会解释缺失的结果。

标签: elasticsearch elasticsearch-java-api resthighlevelclient


【解决方案1】:

今天我在使用以下示例时遇到了同样的问题:

Elastic Scroll API

首先,关于您错过的文档 - 10 是请求大小的默认值,基于此我们可以假设您的一个请求没有得到正确处理。 在您的代码中,未处理第一批 10 个文档:

SearchHit[] searchHits = searchResponse.getHits().getHits();

while 循环之前,您应该遍历您的 searchHits 。 从第一次开始,我在官方文件中并不清楚。

【讨论】:

    【解决方案2】:

    您应该更改您的 while 循环逻辑以先执行命中迭代,然后再执行滚动。

    while (searchHits != null && searchHits.length > 0) {
    
        // execute this block first otherwise the scroll will overwrite the initial hits.
        for (SearchHits hit: searchHits){
            String source=hit.getSourceAsString();
        }
    
        SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
        scrollRequest.scroll(scroll);
        searchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT);
        scrollId = searchResponse.getScrollId();
        searchHits = searchResponse.getHits().getHits();
    }
    

    要考虑的另一件事是您可以增加响应命中大小。来自文档:

    index.max_result_window 默认为 10,000 是一种保障,搜索请求占用堆内存和时间与 from + size 成正比。

    所以max_result_window 的默认值为 10k 点击,您也可以将此值设置为其他值。这意味着您可以在 1 个搜索调用中获取多达 10k 次点击,而不是执行冗余分页。

    您可以通过在执行搜索调用之前为searchSourceBuilder 指定size 属性来做到这一点,如下所示:

    searchSourceBuilder.size(10000); 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多