ES分页

摘要:
//Www.elastic.co/guide/en/lastcsearch/reference/5.3/search请求。html查询时,from参数默认为0,size参数默认为10。+size中的查询结果索引的值不能超过index.max_result_window

本篇文章将会讲解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

没用过,略。

免责声明:文章转载自《ES分页》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇hexdump——Linux系统的二进制文件查看工具安装xtrabackup的时候遇到missing requires of libmysqlclient.so.18()(64bit)解决办法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

sql server规范

常见的字段类型选择 1.字符类型建议采用varchar/nvarchar数据类型 2.金额货币建议采用money数据类型 3.科学计数建议采用numeric数据类型 4.自增长标识建议采用bigint数据类型   (数据量一大,用int类型就装不下,那以后改造就麻烦了) 5.时间类型建议采用为datetime数据类型 6.禁止使用text、ntext、im...

IOS 判断设备屏幕尺寸、分辨率

根据屏幕尺寸和分辨率,ios现在数起来有6个版本。 iOS 设备现有的分辨率如下:iPhone/iPod Touch普通屏                           320像素 x 480像素       iPhone 1、3G、3GS,iPod Touch 1、2、33:2 Retina 屏             640像素 x 960像素...

mongodb 配置均衡器的运行窗口

考虑到数据迁移会降低系统性能,可以配置均衡器在只在特定时间段运行,比如夜里系统负载比较小的时候。详细的配置步骤如下; 连接到任意的mongos服务器,并通过安全认证(如果有认证的话)。 切换到config数据库: use config 启动均衡器: sh.setBalancerState( true ) 配置时间窗口: db.settings.upd...

读写锁

(1) 读写锁是几把锁   一把锁   pthread_rwlock_t lock; (2) 读写锁的类型   读锁: 对内存做读操作   写锁: 对内存做写操作 (3) 读写锁的特性:   线程A加读锁成功, 又来了三个线程, 做读操作, 可以加锁成功     读共享, 并行处理   线程A加写锁成功, 又来了三个线程, 做读操作, 三个线程阻塞    ...

pymysql完成数据的查询操作

import pymysql # 创建连接对象 conn = pymysql.connect(host='localhost', port=3306, user='root', password='mysql',database='python', charset='utf8') # 获取游标对象 cursor = conn.cursor() # 查...

iOS开发 弹簧效果

#import "DDJelloView.h" #define SYS_DEVICE_WIDTH    ([[UIScreen mainScreen] bounds].size.width)                  // 屏幕宽度 #define SYS_DEVICE_HEIGHT   ([[UIScreen mainScreen] bounds...