我们在  springBoot集成elasticsearch(配置篇) 一

             springBoot集成elasticsearch(功能篇) 二

基础上了解了elasticsearch的基本操作。但是我们在查询的时候会遇到一些比较困难的情况。当数据量超过10000的时候就会出现错误。所以,如果使用之前的查询是不行的。所以需要使用游标查询。

特别说明:当数据超过10000的时候,查询数据的时候总数只显示10000。所以如果你要查询更多需要添加:"track_total_hits": true, 

GET /你的索引/_search
{
"track_total_hits": true, 
"query": {
  "match_all": {
    
  }
 }  
}

     

一:在kibana中的查询如下:

1:先查询一下:

GET /索引/_search?scroll=10m 
{
  "sort" : ["_doc"], 
  "query": {
    "match_all": {}
  }, 
  "size": 10000//不能超过1000
}

返回的结果:

{
  "_scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFFNOUDB1M3dCOEpVcklrQ0NIdHl3AAAAAAAAkF0WMjlTLVlDUjJRNjZJZ2pTR3hVWUpiZw==",
  "took" : 75,
  "timed_out" : false,
  "_shards" : {
      .....
  },
  "hits" : {
    .......
   }
}

其中的scroll_id是在下次查询的时候使用。

2:根据1中查询的scroll_id查询接下来10000个的数据。

GET /_search/scroll
{
    "scroll": "1m", 
    "scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFFNOUDB1M3dCOEpVcklrQ0NIdHl3AAAAAAAAkF0WMjlTLVlDUjJRNjZJZ2pTR3hVWUpiZw=="
}

这样查询也会出现scroll_id,一直像2这样查询知道没有数据。这样就可以把所有数据查出来了。

二:使用springBoot实现游标查询

这个时候,我们要根据实际情况。由于数据比较小,只需要查询一次就可以。但是如果数据比较多。那就需要循环的查询数据。

具体步骤首先根据普通查询,但是要要添加一个

//设置游标过期时间
searchRequest.scroll(TimeValue.timeValueSeconds(1000));

这样返回的结果就会有一个scroll_id

scrollId = searchResponse.getScrollId();

然后根据scroll_id查询下面一批数据。一直这样循环往复。

具体代码如下。

   /**
     * 根据游标来查询数据。
     * @param dataView
     * @return
     */
    public List<ScorllDto> query(DataView dataView) {
        //初始化list
        List<ScorllDto> list = new ArrayList<>();
        //初始化查询数据。
        return this.scrollers(null, 10000, list, dataView);
    }

    /**
     * @param sid  分类id
     * @param size 每页数量
     * @param list 存放数据的list
     * @param dataView  查询条件
     * @return
     */
    public List<ScorllDto> scrollers(String sid, Integer size, List<ScorllDto> list, DataView dataView) {
        SearchRequest searchRequest = new SearchRequest(dataView.getKey());
        SearchHit[] hits = null;
        String scrollId = null;

        if (org.apache.commons.lang3.StringUtils.isNotBlank(sid)) {
            SearchScrollRequest scrollRequest = new SearchScrollRequest(sid);
            scrollRequest.scroll(TimeValue.timeValueSeconds(1000));
            SearchResponse searchScrollResponse = null;
            try {

                searchScrollResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT);
                logger.info("查询条件:" + searchScrollResponse);
            } catch (Exception e) {
                logger.info("分页的异常:{}", e.getMessage());
                return list;
            }
            scrollId = searchScrollResponse.getScrollId();
            hits = searchScrollResponse.getHits().getHits();
        } else {

            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

            //3、构造query对象
            BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

            TermQueryBuilder termQueryBuilder = new TermQueryBuilder("state", 1);


            boolQueryBuilder.filter(termQueryBuilder);

            if (dataView.getTime() != null) {
                String timesAgoDate = dataView.getTime() + " 00:00:00";
                String timesNowDate = dataView.getTime() + " 23:59:59";
                Date timesAgo = DateUtil.getLongDate(timesAgoDate);

                Date timesNow = DateUtil.getLongDate(timesNowDate);


                RangeQueryBuilder rangeQueryBuilder = new RangeQueryBuilder("propMainPayTime").timeZone("+08:00").gte(timesAgo).lt(timesNow);
                boolQueryBuilder.must(termQueryBuilder).must(rangeQueryBuilder);

            }


            //4、封装查询体对象属性
            searchSourceBuilder.query(boolQueryBuilder);

            searchSourceBuilder.size(size);
            searchRequest.source(searchSourceBuilder);
            //设置游标过期时间
            searchRequest.scroll(TimeValue.timeValueSeconds(1000));
            SearchResponse searchResponse = null;
            try {
                searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
                logger.info("查询条件:" + searchResponse);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //返回的游标id
            scrollId = searchResponse.getScrollId();
            hits = searchResponse.getHits().getHits();
        }
        //循环取数据。
        for (SearchHit hit : hits) {
            //将数据转换成map
            Map user = JSONObject.toJavaObject(JSON.parseObject(hit.getSourceAsString()), Map.class);

          
            //保存起来
            list.add(scorllDto);
        }
        int mySize = hits.length;
        logger.info("totalValue===>" + mySize);


        if (mySize < size) {
            return list;
        } else {
            return this.scrollers(scrollId, size, list, dataView);
        }
    }

综上就是springBoot集成es的游标查询。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐