Es7.x使用RestHighLevelClient的3種分頁實現(xiàn)

目錄

  1. from+size分頁
    1.1 from+size的命令行實現(xiàn)
    1.2 from+size的RestHighLevelClient實現(xiàn)
  2. scroll 分頁
    2.1 scroll分頁的命令行實現(xiàn)
    2.2 scroll的RestHighLevelClient實現(xiàn)
  3. search_after分頁
    3.1 search_after的命令行實現(xiàn)
    3.2 search_after的的RestHighLevelClient實現(xiàn)
  4. 總結(jié)

正文

ES作為數(shù)據(jù)源的分頁查詢。 數(shù)據(jù)量如果過大叉橱,使用淺分頁可能會引發(fā)性能問題玩裙,可以考慮search_after深分頁蜒谤,當然是要根據(jù)具體業(yè)務(wù)場景進行分析氮帐。

分頁一般有三種方式:

  1. es默認采用的是from+size形式昆庇,在深度分頁的情況下榄棵,這種效率是非常低的嘲更,但是可以隨機跳轉(zhuǎn)頁面筐钟;
  2. scroll search 方式(滾動搜索),官方的建議并不是用于實時的請求赋朦,因為每一個 scroll_id 不僅會占用大量的資源(特別是排序的請求)篓冲,而且是生成的歷史快照,對于數(shù)據(jù)的變更不會反映到快照上北发。這種方式往往用于非實時處理大量數(shù)據(jù)的情況纹因,比如要進行數(shù)據(jù)遷移或者索引變更之類的喷屋。
  3. search_after方式(滾動搜索)琳拨,可以在實時的情況下處理深度分頁,在Es5.x版本后提供的功能屯曹,search_after缺點是不能夠隨機跳轉(zhuǎn)分頁狱庇,只能是一頁一頁的向后翻,并且需要至少指定一個唯一不重復(fù)字段來排序恶耽。

1. from+size分頁

Es封裝RestHighLevelClient和BulkProcessor的工具類

1.1 from+size的命令行實現(xiàn)

GET /test_demo/_search
{
  "query":{
    "match_all": {}
  },
  "from":5000,
  "size":10
}

上面意味著es需要在各個分片上匹配排序并得到5010條數(shù)據(jù)密任,協(xié)調(diào)節(jié)點拿到這些數(shù)據(jù)再進行排序,然后結(jié)果集中取最后10條數(shù)據(jù)返回偷俭。

上述語句性能低的原因:我們只需要10條數(shù)據(jù)浪讳,而es每個分片都需要執(zhí)行from+size條數(shù)據(jù)然后處理后返回。

es為了性能涌萤,會限制我們分頁的深度淹遵,es目前支持最大的max_result_window = 10000,也就是from+size的大小不能超過10000负溪。

image.png

1.2 from+size的RestHighLevelClient實現(xiàn)

    /**
     * 淺分頁查詢
     *
     * @throws IOException
     */
    public static void testPage() throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //排序條件
        searchSourceBuilder.sort("id", SortOrder.ASC);
        searchSourceBuilder.sort("publishTime", SortOrder.DESC);
        //分頁查詢
        searchSourceBuilder.from(2);
        searchSourceBuilder.size(2);
        EsUtil.remoteSearch(searchRequest, searchSourceBuilder);
    }

2. scroll 分頁

在es中我們分頁要請求大數(shù)據(jù)集或者一次請求要獲取大的數(shù)據(jù)集透揣,scroll[skr??l]都是一種非常好的解決方案。

scroll也是滾動搜索川抡。會在第一次搜索的時候辐真,保存一個當時的快照。之后只會基于該舊的視圖快照提供數(shù)據(jù)搜索崖堤。在這個期間發(fā)生變動侍咱,是不會讓用戶看到的。

官方的建議并不是用于實時的請求密幔,因為每一個 scroll_id 不僅會占用大量的資源(特別是排序的請求)楔脯,而且是生成的歷史快照,對于數(shù)據(jù)的變更不會反映到快照上老玛。這種方式往往用于非實時處理大量數(shù)據(jù)的情況淤年,比如要進行數(shù)據(jù)遷移或者索引變更之類的钧敞。

2.1 scroll分頁的命令行實現(xiàn)

  • 第一步:進行搜索,生成scrollId麸粮。
GET test_demo/_search?scroll=1m
{
    "size":2,
    "query":{
        "terms":{
            "tag":[
                "疫情"
            ],
            "boost":"1.0"
        }
    }
}
  • 后續(xù)在使用第一步生成的scrollId進行滾動查詢溉苛。
POST /_search/scroll
{
  "scroll": "5m",
  "scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAylJEWQ3Z4cHRTRzVTeXVqRG9YY1R5Q3hYdw=="
}

2.2 scroll的RestHighLevelClient實現(xiàn)

    public static void testScroll() throws IOException {
        SearchRequest searchRequest = new SearchRequest();

        //失效時間為1min
        Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1));
        //封存快照
        searchRequest.scroll(scroll);
        /**
         * 查詢條件
         */
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("tag", "疫情");
        searchSourceBuilder.query(termQueryBuilder);
        /**
         * 分頁參數(shù)
         */
        searchSourceBuilder.size(2);
        searchRequest.indices("test_demo");

        //放入文檔中
        searchRequest.source(searchSourceBuilder);

        log.info("dsl:" + searchSourceBuilder.toString());
        //遠程查詢
        SearchResponse searchResponse = EsUtil.getRestHighLevelClient().search(searchRequest, RequestOptions.DEFAULT);
        //元素數(shù)量
        Iterator<SearchHit> it1 = searchResponse.getHits().iterator();
        while (it1.hasNext()) {
            SearchHit next = it1.next();
            log.info("輸出數(shù)據(jù):" + next.getSourceAsString());
        }
        log.info("=======================||");
        //計算總數(shù)量
        long totalCount = searchResponse.getHits().getTotalHits().value;
        //得到總頁數(shù)
        int page = (int) Math.ceil((float) totalCount / 2);
        //多次遍歷分頁,獲取結(jié)果
        String scrollId = searchResponse.getScrollId();
        for (int i = 1; i <= page; i++) {
            //獲取到該id
            SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
            searchScrollRequest.scroll(scroll);
            SearchResponse response = EsUtil.getRestHighLevelClient().scroll(searchScrollRequest, RequestOptions.DEFAULT);
            //打印數(shù)據(jù)
            SearchHits hits = response.getHits();
            scrollId = response.getScrollId();
            Iterator<SearchHit> iterator = hits.iterator();
            while (iterator.hasNext()) {
                SearchHit next = iterator.next();
                log.info("輸出數(shù)據(jù):" + next.getSourceAsString());
            }
            log.info("=======================");
        }
    }

3. search_after分頁

可以在實時的情況下處理深度分頁弄诲,在Es5.x版本后提供的功能愚战,search_after缺點是不能夠隨機跳轉(zhuǎn)分頁,只能是一頁一頁的向后翻齐遵,并且需要至少指定一個唯一不重復(fù)字段來排序寂玲。

3.1 search_after的命令行實現(xiàn)

注意:search_after必須指定一個唯一不重復(fù)的字段來排序,此處我們指定了兩個字段進行排序梗摇,

該例子:id是唯一不重復(fù)字段拓哟,publishTime可能會重復(fù)。

GET test_demo/_search
{
  "query": {
    "match_all": {
      
    }
  },
    "size": 2,
    "sort":[
      {"id":"asc"},
      {"publishTime":"desc"}
    ]
}
image.png

注意伶授,結(jié)果返回的sort字段断序,存儲的是最后一組的排序字段的值,而search_after在下次搜索時糜烹,需要攜帶該數(shù)據(jù)违诗。

image.png

最終完成了滾動分頁操作。

3.2 search_after的的RestHighLevelClient實現(xiàn)

    public static void testSearchAfter() throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //排序條件
        searchSourceBuilder.sort("id", SortOrder.ASC);
        searchSourceBuilder.sort("publishTime", SortOrder.DESC);
        //分頁查詢
        searchSourceBuilder.size(2);
        List<SearchHit> remoteSearch = EsUtil.remoteSearch(searchRequest, searchSourceBuilder);
        //查詢最后一筆數(shù)據(jù)
        SearchHit result = remoteSearch.get(remoteSearch.size() - 1);
        //序列化為對象
        //分頁查詢下一頁數(shù)據(jù)
        log.info("=====================下一頁============================");
        SearchRequest searchRequest2 = new SearchRequest();
        SearchSourceBuilder searchSourceBuilder2 = new SearchSourceBuilder();
        //排序條件
        searchSourceBuilder2.sort("id", SortOrder.ASC);
        searchSourceBuilder2.sort("publishTime", SortOrder.DESC);

        //存儲上一次分頁的sort信息
        searchSourceBuilder2.searchAfter(result.getSortValues());
        searchSourceBuilder2.size(2);
        EsUtil.remoteSearch(searchRequest2, searchSourceBuilder2);
    }

4. 總結(jié)

image.png

推薦閱讀

Elasticsearch 深入理解search After 處理深度分頁問題

elasticsearch深度分頁問題

Es封裝RestHighLevelClient和BulkProcessor的工具類

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末疮蹦,一起剝皮案震驚了整個濱河市诸迟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌愕乎,老刑警劉巖阵苇,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異妆毕,居然都是意外死亡慎玖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門笛粘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來趁怔,“玉大人,你說我怎么就攤上這事薪前∪笈” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵示括,是天一觀的道長铺浇。 經(jīng)常有香客問我,道長垛膝,這世上最難降的妖魔是什么鳍侣? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任丁稀,我火速辦了婚禮,結(jié)果婚禮上倚聚,老公的妹妹穿的比我還像新娘线衫。我一直安慰自己,他們只是感情好惑折,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布授账。 她就那樣靜靜地躺著,像睡著了一般惨驶。 火紅的嫁衣襯著肌膚如雪白热。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天粗卜,我揣著相機與錄音屋确,去河邊找鬼。 笑死休建,一個胖子當著我的面吹牛乍恐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播测砂,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼百匆!你這毒婦竟也來了砌些?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤加匈,失蹤者是張志新(化名)和其女友劉穎存璃,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雕拼,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡纵东,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了啥寇。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片偎球。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖辑甜,靈堂內(nèi)的尸體忽然破棺而出衰絮,到底是詐尸還是另有隱情,我是刑警寧澤磷醋,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布猫牡,位于F島的核電站,受9級特大地震影響邓线,放射性物質(zhì)發(fā)生泄漏淌友。R本人自食惡果不足惜煌恢,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望震庭。 院中可真熱鬧症虑,春花似錦、人聲如沸归薛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽主籍。三九已至习贫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間千元,已是汗流浹背苫昌。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留幸海,地道東北人祟身。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像物独,于是被迫代替她去往敵國和親袜硫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容