使用from size進行分頁查詢(深度分頁),當數據量大的時候,對全部數據進行遍歷,使用from size性能會很差。from指的是從哪里開始拿數據,size是結果集中返回的文檔個數。from-size的工作原理是:如size=10&from=100,那么Elasticsearch會從每個分片里取出110條數據,然后匯集到一起再排序,取出101~110序號的文檔。由此可見,from-size的效率必然不會很高,特別是分頁越深,需要排序的數據越多,其效率就越低。
Elasticsearch中進行大數據量查詢時,往往因為設備、網絡傳輸問題影響查詢數據的效率;Elasticsearch中提供了Scroll(游標)的方式對數據進行少量多批次的滾動查詢,來提高查詢效率。
/** * 查詢所有數據 * * @param index 索引名稱 * @param type type 6.0后不推薦使用 * @param fields 需要顯示的字段 * @param sortField 需要進行排序的字段 * @param highlightField 需要高亮的字段 * @param queryBuilder 查詢條件 * @return */ public static List<Map<String, Object>> searchAllData(String index, String type, String fields, String sortField, String highlightField,QueryBuilder queryBuilder ) { //指定一個index和type SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index).setTypes(type); // 高亮(xxx=111,aaa=222) if (StringUtils.isNotEmpty(highlightField)) { HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.preTags("<span style='color:red;font-weight:bold'>");//設置前綴 highlightBuilder.postTags("</span>");//設置后綴 // 設置高亮字段 highlightBuilder.field(highlightField); searchRequestBuilder.highlighter(highlightBuilder); } // 需要顯示的字段,逗號分隔(缺省為全部字段) if (StringUtils.isNotEmpty(fields)) { searchRequestBuilder.setFetchSource(fields.split(","), null); } searchRequestBuilder.setFetchSource(true); if (StringUtils.isNotEmpty(sortField)) { searchRequestBuilder.addSort(sortField, SortOrder.ASC); } //設置每批讀取的數據量 searchRequestBuilder.setSize(100); //查詢條件 searchRequestBuilder.setQuery(queryBuilder); //設置 search context 維護1分鍾的有效期 searchRequestBuilder.setScroll(TimeValue.timeValueMinutes(1)); //獲得首次的查詢結果 SearchResponse scrollResp=searchRequestBuilder.get(); //打印的內容 可以在 Elasticsearch head 和 Kibana 上執行查詢 LOGGER.info("\n{}", searchRequestBuilder); //打印命中數量 LOGGER.info("命中總數量:{}", scrollResp.getHits().getTotalHits()); List<Map<String, Object>> sourceList = new ArrayList<Map<String, Object>>(); StringBuffer stringBuffer = new StringBuffer(); do { //將scorllId循環傳遞 scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(TimeValue.timeValueMinutes(1)).execute().actionGet(); for (SearchHit searchHit : scrollResp.getHits().getHits()) { searchHit.getSourceAsMap().put("id", searchHit.getId()); if (StringUtils.isNotEmpty(highlightField)) { if (!ObjectUtils.isEmpty(searchHit.getHighlightFields().get(highlightField))) { Text[] text = searchHit.getHighlightFields().get(highlightField).getFragments(); if (text != null) { for (Text str : text) { stringBuffer.append(str.string()); } //遍歷 高亮結果集,覆蓋 正常結果集 searchHit.getSourceAsMap().put(highlightField, stringBuffer.toString()); } } } sourceList.add(searchHit.getSourceAsMap()); } //當searchHits的數組為空的時候結束循環,至此數據全部讀取完畢 } while(scrollResp.getHits().getHits().length != 0); //刪除scroll ClearScrollRequest clearScrollRequest = new ClearScrollRequest(); clearScrollRequest.addScrollId(scrollResp.getScrollId()); client.clearScroll(clearScrollRequest).actionGet(); return sourceList; }
————————————————
版權聲明:本文為CSDN博主「Haoyugg」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_41127890/article/details/82219811