ES查询量超过一万时候,采用滑动查询来解决

机缘

项目中ES数据量比较大,这一次有一个bug就是数据超过1W的 没有获取到。其实自己知道ES查询返回条目最多10000条,可自己总觉得这种情况很少,所以就没特别注意,这次出现了,就做个笔记,分享给大家,也方便自己下次使用


实际代码

/**

- 查询ES通用方法
  *

- @param userExportHitList

- @param index

- @param boolQueryBuilder

- @Author 张威威

- @Date 2023/10/17
  */
  private void queryEs(List<UserExportHit> userExportHitList, String index, BoolQueryBuilder boolQueryBuilder, List<DataSecuritySpaceHit> dataSecuritySpaceHitList) throws IOException {
  //处理数据量大于10000的时候,采用滚动查询
  Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L));
  SearchRequest searchRequest = new SearchRequest(index);
  SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  //sourceBuilder.fetchSource(index,null);
  sourceBuilder.query(boolQueryBuilder);
  sourceBuilder.size(10000);
  IndicesOptions indicesOptions = IndicesOptions.LENIENT_EXPAND_OPEN;
  searchRequest.indicesOptions(indicesOptions);
  //加入scroll和构造器
  searchRequest.scroll(scroll);
  searchRequest.source(sourceBuilder);
  log.info("~~~~~~~查询ES请求体 query:{}~~~~~~~~~", searchRequest);
  List<String> scrollIdList = new ArrayList<>();
  RestHighLevelClient client = (RestHighLevelClient) SpringUtils.getBean(ElasticsearchAuditConfig.NAME);
  SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
  //拿到都一个scrollId(游标)
  String scrollId = searchResponse.getScrollId();
  SearchHit[] hits = searchResponse.getHits().getHits();
  //添加下标进集合
  scrollIdList.add(scrollId);

  try {
      while (ArrayUtils.isNotEmpty(hits)) {
          for (SearchHit hit : hits) {
              Map<String, Object> map = hit.getSourceAsMap();
              Long systemTime = (Long) map.get("system_time");
              String oprUserAccount = (String) map.get("opr_user_account");
              if (null != systemTime && StringUtils.isNotBlank(oprUserAccount)) {
                  Date date = new Date(systemTime);
                  UserExportHit userExportHit = new UserExportHit();
                  userExportHit.setExportTime(date);
                  userExportHit.setOprUserAccount(oprUserAccount);

  ```
              String oprMenuname = (String) map.get("opr_menu_name");
              String systemIp = (String) map.get("system_ip");
              String oprUserName = (String) map.get("opr_user_name");
              String oprOrgCode = (String) map.get("opr_org_code");
              String id = hit.getId();
              Integer exportnum = (Integer) map.get("export_num");
              userExportHit.setSystemTime(systemTime);
              userExportHit.setOprMenuName(oprMenuname);
              userExportHit.setSystemIp(systemIp);
              userExportHit.setOprUserName(oprUserName);
              userExportHit.setOprOrgCode(oprOrgCode);
              userExportHit.setExportNum(exportnum);
              userExportHit.setLogId(id);
              userExportHitList.add(userExportHit);
          }
  
          String account = (String) map.get("account");
          String opt = (String) map.get("opt");
          String targetIp = (String) map.get("targetIp");
          Long eventTimestamp = (Long) map.get("eventTimestamp");
          if (StringUtils.isNotBlank(account) && StringUtils.isNotBlank(opt) && null != eventTimestamp) {
              DataSecuritySpaceHit dataSecuritySpaceHit = new DataSecuritySpaceHit();
              dataSecuritySpaceHit.setAccount(account);
              Date date = new Date(eventTimestamp);
              dataSecuritySpaceHit.setTime(date);
              dataSecuritySpaceHit.setOpt(opt);
              dataSecuritySpaceHit.setTargetIp(targetIp);
              dataSecuritySpaceHitList.add(dataSecuritySpaceHit);
          }
      }
      if (hits.length < 10000) {
          log.info("es滚动完了,结束就行");
          break;
      }
      //继续滚动
      SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
      searchScrollRequest.scroll(scroll);
      SearchResponse response = client.scroll(searchScrollRequest, RequestOptions.DEFAULT);
      scrollId = response.getScrollId();
      hits = response.getHits().getHits();
      scrollIdList.add(scrollId);
  }
  ```

  } finally {
      ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
      clearScrollRequest.setScrollIds(scrollIdList);
      client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
  }
  }

憧憬

愿天下没有bug

当使用ES进行查询时,可能会遇到超过一万的结果返回问题。这是由于ES的默认设置造成的,其限制了单个查询的返回结果为一万。但我们可以通过以下几种方法来解决这个问题: 1. Scroll API(滚动查询):我们可以使用Scroll API来实现分段加载大数据。通过切分查询,每次请求一部分数据,并使用scroll ID进行下一次请求,直到获取所有的结果。 2. 分页查询:我们可以使用ES的分页功能来控制返回结果的数。通过设置from和size参数,我们可以指定返回结果的起始位置和数,从而分批加载数据。 3. 查询优化:一千以上的查询结果可能会导致性能下降,因此可以考虑优化查询,减少返回结果的数。可以通过以下几种方法来实现: - 使用过滤器(filter)替代查询(query):过滤器不会计算相关性得分,可以更快地返回结果。 - 限制查询的时间范围:如果查询的数据集非常庞大,可以通过限制时间范围来减少结果数。 - 优化查询语句:使用更精确的查询件,可以减少返回结果的数。 4. 聚合查询:如果我们只关心数据的统计信息,可以使用聚合查询来替代普通的查询。聚合查询可以对数据进行分组、计数、求和等统计操作,返回的数据更少。 总之,当使用ES进行查询时,如果结果超过一万,我们可以通过Scroll API、分页查询、优化查询和聚合查询等方法来解决这个问题,提高查询性能,并且有效地处理大数据查询结果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值