zoukankan      html  css  js  c++  java
  • ES分页

    本篇文章将会讲解ES两种分页查询方法以及优缺点

    注意:以下文章中的命令和java代码均基于ES5.3.0版本

    一、from/size分页

    官网文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/5.3/search-request-from-size.html

    查询的时候带上from和size两个参数即可

    • from参数默认为0,size参数默认为10
    • 查询结果索引 from + size 的值不能超出index.max_result_window,默认该值是10000
    • 如果想做深度分页,可以考虑使用 Scroll 或者Search After 方式。

    1.修改默认窗口大小

    PUT请求 `{{es-host}}/索引名字/_settings

    {
        "index": {
            "max_result_window": 1000000
        }
    }
    

    可以适当增大窗口值大小方便常用分页查询

    2.JAVA API

    transportClient.prepareSearch(索引名)
                    .setQuery(mixQuery)
                    .setFrom((pageNum - 1) * pageSize)
                    .setSize(pageSize)
                    .setFetchSource(true);
    

    3.优缺点

    优点就是简单,和mysql的分页很相似

    缺点也很明显,首先,分页受限于结果窗口大小,而该值默认值仅仅是10000,就算可以调整该分页大小,仍然让人心里不爽快,再者,随着分页from的值越来越大,效率会越来越低。from/size的分页原理是先查询出所有结果,然后根据from和size进行结果截取,所以势必会随着分页深度的增加效率越来越低。最后,由于需要将查询结果都加载到内存,有可能会出现内存爆掉的情况发生。

    二、Scroll分页

    从from/size的官网为文档上来看,如果需要“深分页”,最好使用Scroll or Search After API。

    官网文档:https://www.elastic.co/guide/en/elasticsearch/reference/5.3/search-request-scroll.html

    scroll效率之所以高,是因为它内部维护着一个“游标”,类似于指针的东西,每次查询完size个数据,游标就会移动到查询数据的尾部等待下次查询。

    1.初次请求

    请求方式

    POST

    请求地址

    {{es-host}}/website/_search?scroll=1m

    请求体

    {
        "size": 1,
        "query": {
            "match_all": {}
        }
    }
    

    响应结果

    {
        "_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAANLb6Flg4V2VGRndwUW91SnBVWUlxcTJzc2cAAAAAADS2-RZYOFdlRkZ3cFFvdUpwVVlJcXEyc3NnAAAAAAA0tvgWWDhXZUZGd3BRb3VKcFVZSXFxMnNzZwAAAAAANLb8Flg4V2VGRndwUW91SnBVWUlxcTJzc2cAAAAAADS2-xZYOFdlRkZ3cFFvdUpwVVlJcXEyc3Nn",
        "took": 1,
        "timed_out": false,
        "_shards": {
            "total": 5,
            "successful": 5,
            "failed": 0
        },
        "hits": {
            "total": 5,
            "max_score": 1.0,
            "hits": [
                {
                    "_index": "website",
                    "_type": "blog",
                    "_id": "AXoGPweiCycsj4NKux3V",
                    "_score": 1.0,
                    "_source": {
                        "name": "test"
                    }
                }
            ]
        }
    }
    

    初次请求和正常的请求没什么区别,就加上一个参数scroll=1m即可,表示本次scroll游标一分钟内有效。

    接着,拿到的结果中除了正常返回的数据,还多了一个_scroll_id参数,下次请求就可以直接使用该参数进行分页查询了。

    2.以后的请求

    请求方式

    GET

    请求地址

    {{es-host}}/_search/scroll?scroll=1m&scroll_id=DnF1ZXJ5VGhlbkZldGNoBQAAAAAANL04FmJrRjY5VkpFUm0yMjZvc2s5VF91S0EAAAAAADS9NhZia0Y2OVZKRVJtMjI2b3NrOVRfdUtBAAAAAAA0vTcWYmtGNjlWSkVSbTIyNm9zazlUX3VLQQAAAAAANL05FmJrRjY5VkpFUm0yMjZvc2s5VF91S0EAAAAAADS9OhZia0Y2OVZKRVJtMjI2b3NrOVRfdUtB

    请求体

    响应结果

    {
        "_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAANL04FmJrRjY5VkpFUm0yMjZvc2s5VF91S0EAAAAAADS9NhZia0Y2OVZKRVJtMjI2b3NrOVRfdUtBAAAAAAA0vTcWYmtGNjlWSkVSbTIyNm9zazlUX3VLQQAAAAAANL05FmJrRjY5VkpFUm0yMjZvc2s5VF91S0EAAAAAADS9OhZia0Y2OVZKRVJtMjI2b3NrOVRfdUtB",
        "took": 1,
        "timed_out": false,
        "terminated_early": true,
        "_shards": {
            "total": 5,
            "successful": 5,
            "failed": 0
        },
        "hits": {
            "total": 5,
            "max_score": 1.0,
            "hits": [
                {
                    "_index": "website",
                    "_type": "blog",
                    "_id": "AXlizj8kCycsj4NKuvL8",
                    "_score": 1.0,
                    "_source": {
                        "name": "cve-2015-1427"
                    }
                }
            ]
        }
    }
    

    可以看到,再次请求的时候不需要再指定索引名称和相关的复杂查询条件,直接告诉ES上一次查询的游标_scroll_id即可。

    3.JAVA API

    SearchRequestBuilder searchRequestBuilder = transportClient.prepareSearch(index.split(","))
                    .setQuery(mixQuery)
                    .setSize(pageSize)
                    .setFetchSource(true)
                    .setScroll(TimeValue.timeValueMinutes(1))
                    .addSort(fieldSortBuilder);
    

    只需要加上 .setFetchSource(true)即可。

    第一次查询之后要正常处理结果数据,并非像是某些文章中讲的只是返回scroll_id

    之后的查询则就简单多了

    scrollId = searchResponse.getScrollId();
            while (searchResponse.getHits().getHits().length > 0) {
    //处理结果数据
                SearchScrollRequestBuilder searchScrollRequestBuilder = transportClient.prepareSearchScroll(scrollId).setScroll(TimeValue.timeValueMinutes(1));
                searchResponse = searchScrollRequestBuilder.execute().actionGet();
                scrollId = searchResponse.getScrollId();
            }
    

    三、Search After分页

    文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/5.3/search-request-search-after.html

    没用过,略。

  • 相关阅读:
    终端等级UE Category—4G数据传输流程系列(五)
    4G数据传输流程系列(四)—物理层OFDM、MIMO实现
    4G数据传输流程系列(三)—物理层“从传输块到码字”
    4G网络数据传输流程与速率分析(二)--资源调度
    4G网络数据传输流程与速率分析系列(一)
    G.711 u律;A律 压缩算法
    VLAN IEEE802.1Q
    64B/66B编码
    Operator与优化
    对偶与Proximal
  • 原文地址:https://www.cnblogs.com/kuangdaoyizhimei/p/14886472.html
Copyright © 2011-2022 走看看