ES(Elasticsearch)分页查询通常使用 from
和 size
参数来控制查询结果的分页。from
用于指定从哪个结果开始,size
用于指定返回多少条记录。
示例查询
假设你想查询 my_index
索引,并且希望分页获取数据:
json
GET /my_index/_search { "from": 0, "size": 10, "query": { "match_all": {} } }
参数解释:
from
: 表示从第几条记录开始(默认为0,表示从第一条开始)。size
: 表示每页返回多少条记录。
分页逻辑:
- 第一页:
from = 0
,size = 10
(返回从0到9的记录)。 - 第二页:
from = 10
,size = 10
(返回从10到19的记录)。 - 第三页:
from = 20
,size = 10
(返回从20到29的记录)。
注意事项:
- 当你分页查询时,如果数据量非常大,建议使用
search_after
进行深分页,它比from/size
更高效。 from
和size
使用时会增加查询的开销,特别是在大数据集上。
from size
public List<ResFoodOrderInspectionVO> queryGroupByOrgGroupLocationCode(ReqFoodOrderInspectionVO reqVO) {log.info("食用订单巡检表查询条件:{}", reqVO.toString());StopWatch stopwatch = new StopWatch();stopwatch.start();List<ResFoodOrderInspectionVO> resList = Lists.newArrayList();SearchRequest searchRequest = new SearchRequest(EsOperateTables.FOOD_ORDER_INSPECTION_V2.getAlias());SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.fetchSource(RES_FBASEFOODORDERINSPEC_FIELDS, null);
// searchSourceBuilder.size(0);// 设置为0代表不需要取查询到的所有数据,只需要取聚合的相关的数据searchSourceBuilder.size(reqVO.getSize());searchSourceBuilder.from((reqVO.getPage() - 1) * reqVO.getSize());BoolQueryBuilder booleanQuery = QueryBuilders.boolQuery();// 组装查询条件buildBooleanQuery(booleanQuery, reqVO);searchSourceBuilder.query(QueryBuilders.constantScoreQuery(booleanQuery));// 分组,统计,排序FoodOrderInspectionConvertor.groupCountAgg(searchSourceBuilder, reqVO, foodOrderInspectionDisabled);searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = null;try {searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);stopwatch.stop();} catch (IOException e) {log.error(ErrorMsgConstant.FOODORDERINSPECTION_QUERYES_ERROR, e);throw new OrderCenterException(ErrorMsgConstant.FOODORDERINSPECTION_QUERYES_ERROR);}if (Objects.isNull(searchResponse)) {return Collections.emptyList();}Terms terms = searchResponse.getAggregations().get(FoodOrderInspectionConstant.GROUPDIMENSION);if (Objects.isNull(terms)) {return Collections.emptyList();}// 包含门店,且按日统计时,需要判断总量,其他场景,总分组量实际不会大于10000,不需要判断if (CollectionUtils.isNotEmpty(reqVO.getLocationCodes()) && !reqVO.getGroupMonth() && searchResponse.getHits().getTotalHits() > FoodOrderInspectionConstant.GROUP_RETURN_SIZE) {throw new OrderCenterException(ErrorMsgConstant.GROUP_TOTALSIZE_TOOLONG);}// 组装数据for (Terms.Bucket entry : terms.getBuckets()) {resList.add(FoodOrderInspectionConvertor.toResVO(entry, reqVO));}// 取聚合统计后合计Map<String, Aggregation> totalMap = searchResponse.getAggregations().getAsMap();resList.forEach(v -> {v.setResFoodOrderInspectionTotalVO(FoodOrderInspectionConvertor.buildTotal(totalMap));});log.info("食用订单巡检报表查询耗时:{}", stopwatch.getTotalTimeMillis());return resList;}}
searchAfter
private SearchRequest buildSearchRequest(EsSchemel esSchemel, QueryBuilder params, int pageSize, String orderBy, String scrollId) {if (pageSize > 10000) {//fixed:es error,from + size must be less than or equal to: [10000]pageSize = 10000;}SearchRequest searchRequest = new SearchRequest(esSchemel.getIndex());searchRequest.types(esSchemel.getType());SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder.query(params);//sourceBuilder.from(pageNo - 1);sourceBuilder.size(pageSize);sourceBuilder.timeout(new TimeValue(30, TimeUnit.SECONDS));if (esSchemel.getSelectCols() != null && esSchemel.getSelectCols().length > 0) {//性能参数,减少iosourceBuilder.fetchSource(esSchemel.getSelectCols(), EXCLUDEFIELDS);}if (!Strings.isNullOrEmpty(orderBy)) {sourceBuilder.sort(new FieldSortBuilder(orderBy).order(SortOrder.DESC));if (!Strings.isNullOrEmpty(scrollId)) {sourceBuilder.searchAfter(new Object[]{scrollId});}}searchRequest.source(sourceBuilder);return searchRequest;}