java处理ES查询突破10000条的限制方案

1.为什么要限制10000条

 默认情况下,Elasticsearch集群中每个分片的搜索结果数量限制为10000。这是为了避免潜在的性能问题。

2.突破10000条限制的办法

  1. 使用scroll API:scroll API可以帮助我们在不加载所有数据的情况下获取所有结果。它会在后台执行查询以获取滚动ID,并将其用于进行后续查询。这样就可以一次性获取所有结果,而不必担心限制
  2. 修改ES默认设置,将10000修改成10万或者50万,这样的话要考虑ES内存溢出的问题,不推荐

3.具体方法

  1. 使用scroll API
public ConcurrentLinkedDeque<FramePickingInfoVo> getSearchRequest(FramePickingPageVo vo){
        long start = System.currentTimeMillis();
        ConcurrentLinkedDeque<FramePickingInfoVo> list=new ConcurrentLinkedDeque<>();
        try{
            //构建查询请求
            SearchRequest baseSubOrderIndexRequest = CloudBaseQueryBuilder.getBaseSubOrderIndexRequest();
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQuery = CloudBaseQueryBuilder.getBaseFramePickBoolQuery(vo,true);
            //设置size(10000)
            sourceBuilder.size(batchSize);
            sourceBuilder.query(boolQuery);
            //设置排序方式
            getSort(vo.getOrderByType(),sourceBuilder);
            // 滚动查询请求
            SearchRequest searchRequest = new SearchRequest(BASE_SUB_ORDER_DIMENSION_INDEX);
            searchRequest.source(sourceBuilder);
            //设置请求滚动时间窗口时间
            searchRequest.scroll(TimeValue.timeValueMinutes(scrollTime));

            //执行首次检索
            SearchResponse searchResponse = elasticsearchClient.search(searchRequest, RequestOptions.DEFAULT);

            //首次检索返回scrollId,用于下一次的滚动查询
            String scrollId = searchResponse.getScrollId();
            //获取首次检索命中结果

            SearchHit[] searchHits = searchResponse.getHits().getHits();
            ConcurrentLinkedDeque<FramePickingInfoVo> framPickDateInfos = getFramPickDateInfos(searchResponse);
            list.addAll(framPickDateInfos);
            // 处理滚动结果
            while (searchHits != null && searchHits.length > 0) {
                SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
                scrollRequest.scroll(TimeValue.timeValueMinutes(scrollTime));

                searchResponse = elasticsearchClient.scroll(scrollRequest, RequestOptions.DEFAULT);
                scrollId = searchResponse.getScrollId();
                searchHits = searchResponse.getHits().getHits();
                ConcurrentLinkedDeque<FramePickingInfoVo> framPickDateInfos1 = getFramPickDateInfos(searchResponse);
                list.addAll(framPickDateInfos1);
            }

            // 清理滚动上下文
            ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
            clearScrollRequest.addScrollId(scrollId);

            ClearScrollResponse clearScrollResponse = elasticsearchClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
            boolean succeeded = clearScrollResponse.isSucceeded();

            long end = System.currentTimeMillis();
            System.out.println("共执行时间:" + (end - start) / 1000 + " s");

        } catch (Exception e) {
            System.out.println("===error==" + e.getMessage());
            e.printStackTrace();
        }
        return list;
    }
  1. 修改ES默认配置
# 调大查询窗口巨细,比方100w
PUT index/_settings
{
  "index.max_result_window": "1000000"
}
# 检查查询最大数
GET index/_settings
---
{
  "demo_scroll" : {
    "settings" : {
      "index" : {
        "number_of_shards" : "5",
        "provided_name" : "demo_scroll",
        "max_result_window" : "1000000",
        "creation_date" : "1680832840425",
        "number_of_replicas" : "1",
        "uuid" : "OLV5W_D9R-WBUaZ_QbGeWA",
        "version" : {
          "created" : "6082399"
        }
      }
    }
  }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Elasticsearch中,通过使用Search After API可以解决默认返回10000数据限制。这个API可以让你从上一个查询结果的最后一记录开始下一次查询。这个API需要一个游标参数,这个参数是上一次查询结果中最后一记录的排序值,然后下一次查询时将这个参数传入就可以继续从这个游标位置开始查询。 在Java中使用Search After API,你需要使用SearchRequestBuilder和SearchResponse对象。首先,你需要构建一个SearchRequestBuilder实例,然后设置查询件和游标参数。接着,你可以通过execute()方法执行查询,并且可以从SearchResponse对象中获取结果。 以下是一个使用Search After API进行查询的示例代码: ``` SearchRequestBuilder searchRequestBuilder = client.prepareSearch("index_name") .setTypes("doc_type") .setQuery(QueryBuilders.matchAllQuery()) .addSort(SortBuilders.fieldSort("sort_field").order(SortOrder.ASC)) .setSize(100); SearchResponse searchResponse = searchRequestBuilder.execute().actionGet(); while (true) { SearchHits hits = searchResponse.getHits(); if (hits.getHits().length == 0) { break; } for (SearchHit hit : hits) { // 处理查询结果 } // 获取最后一记录的排序值作为游标参数 SearchHit lastHit = hits.getHits()[hits.getHits().length - 1]; Object[] sortValues = lastHit.getSortValues(); // 设置游标参数并继续查询 searchRequestBuilder = client.prepareSearch("index_name") .setTypes("doc_type") .setQuery(QueryBuilders.matchAllQuery()) .addSort(SortBuilders.fieldSort("sort_field").order(SortOrder.ASC)) .setSize(100) .setSearchAfter(sortValues); searchResponse = searchRequestBuilder.execute().actionGet(); } ``` 在上面的示例代码中,我们首先设置了查询件和排序参数,然后执行第一次查询,并且通过获取最后一记录的排序值作为游标参数,然后设置游标参数并执行下一次查询,直到查询结果为空为止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值