ElasticSearch如何一次查詢出全部數據


使用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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM