1. 程式人生 > >elasticsearch 大資料場景下使用scroll實現分頁查詢

elasticsearch 大資料場景下使用scroll實現分頁查詢

es查詢大批量資料的”可能方案”

當使用es來請求大批量資料時,通常有三種辦法,其一:直接查詢獲取全量資料;其二:使用setFrom以及setSize解決;其三:使用es自帶的scroll分頁支援

方案評估


對於上述方案的評估,此處建議大家可以先看看這篇文章 Elasticsearch 搜尋內部執行原理

方案選擇


經上述評估,顯然,最終採取scroll進行分頁實現,分頁後的資料處理有兩種方式可供處理。第一種,獲取分頁後的資料再聚合;第二種,直接處理分頁後的資料。對於第一種,如若聚合後的資料有幾十萬、上百萬,乃至更多,那勢必會導致系統記憶體飆升,jvm老年代可能會被迅速打滿,進而促發full gc, 若full gc後仍得不到可用空間,可能會造成oom,服務直接不可用。所以第一種處理方式是存在風險的,推薦使用第二種

核心程式碼


假定各位maven已配置好,es處於可用狀態
使用scroll分頁主要分為2步,第1步,初始化查詢,獲取scrollId。第2步使用scrollId迭代查詢

  • 初始化查詢
    //構建查詢條件(非必須)
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    boolQueryBuilder.must(QueryBuilders.matchQuery("rate_object","item"));
        RangeQueryBuilder publishDateBuilder = QueryBuilders.rangeQuery
("created_at"); publishDateBuilder.from("2018-04-22 00:00:00");//格式需要同你建立索引時的格式匹配 boolQueryBuilder.filter(publishDateBuilder); TransportClient client = factory.getClient(); SearchResponse response = client.prepareSearch("index")//對應索引 .setTypes("type")//對應索引type .setQuery
(boolQueryBuilder) .setScroll(TimeValue.timeValueMinutes(10)) .setSize(100) .execute() .actionGet();
  • 迭代查詢
//此處實現迭代的方式較多,僅列其一,
while (response.getHits().getHits().length>0) {
            String scrollId = response.getScrollId();
            response = client.prepareSearchScroll(scrollId)
                    .setScroll(TimeValue.timeValueMinutes(10))//設定查詢context的存活時間
                    .execute()
                    .actionGet();

            SearchHits hits = response.getHits();
            for (SearchHit hit:hits.getHits()) {
                String hitString = hit.getSourceAsString();
                System.out.println(hitString);//此處可進行業務邏輯
            }         
        }

注:處理結束後,記得clean scroll

ClearScrollRequest request = new ClearScrollRequest();
        request.addScrollId(response.getScrollId());
        client.clearScroll(request);

留下此篇部落格以供自己日後參考