elasticsearch 查询_ElasticSearch教程之---Scroll查询

54a5fb22083e3284cee444997b980011.png

作者:千锋老魏

源码地址:https://github.com/qfjiaoyan/elasticsearch-examples

ES对于from+size的个数是有限制的,二者之和不能超过1w。当所请求的数据总量大于1w时,可用scroll来代替from+size。

1.7.1 原理

ES的搜索是分2个阶段进行的,即Query阶段和Fetch阶段。 Query阶段比较轻量级,通过查询倒排索引,获取满足查询结果的文档ID列表。 而Fetch阶段比较重,需要将每个shard的结果取回,在协调结点进行全局排序。 通过From+size这种方式分批获取数据的时候,随着from加大,需要全局排序并丢弃的结果数量随之上升,性能越来越差。

而Scroll查询,先做轻量级的Query阶段以后,免去了繁重的全局排序过程。 它只是将查询结果集,也就是doc id列表保留在一个上下文里, 之后每次分批取回的时候,只需根据设置的size,在每个shard内部按照一定顺序(默认doc_id续), 取回这个size数量的文档即可。

1.7.2 使用场景

由此也可以看出scroll不适合支持那种实时的和用户交互的前端分页工作,其主要用途用于从ES集群分批拉取大量结果集的情况,一般都是offline的应用场景。 比如需要将非常大的结果集拉取出来,存放到其他系统处理,或者需要做大索引的reindex等等。 不要把 scroll 用于实时请求,它主要用于大数据量的场景。例如:将一个索引的内容索引到另一个不同配置的新索引中。

1.7.3 JAVA代码示例

例如滚动查询所有文档:

POST 127.0.0.1:9200/my_index/_search?scroll=1m{    "query": {        "match_all" : {}    },    "sort": [        "_doc"        ]    }}

清除scroll

虽然我们在设置开启scroll时,设置了一个scroll的存活时间,但是如果能够在使用完顺手关闭,可以提早释放资源,降低ES的负担.

DELETE 127.0.0.1:9200/_search/scroll{    "scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAdsMqFmVkZTBJalJWUmp5UmI3V0FYc2lQbVEAAAAAAHbDKRZlZGUwSWpSVlJqeVJiN1dBWHNpUG1RAAAAAABpX2sWclBEekhiRVpSRktHWXFudnVaQ3dIQQAAAAAAaV9qFnJQRHpIYkVaUkZLR1lxbnZ1WkN3SEEAAAAAAGlfaRZyUER6SGJFWlJGS0dZcW52dVpDd0hB"}

JAVA代码示例:com.qianfeng.elasticsearch.query.impl.BaseQueryImpl

@Overridepublic void scrollQuery(String indexName, String typeName) throws IOException {    SearchRequest searchRequest = new SearchRequest(indexName);    searchRequest.types(typeName);    //初始化scroll    //值不需要足够长来处理所有数据—它只需要足够长来处理前一批结果。每个滚动请求(带有滚动参数)设置一个新的过期时间。    final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L)); //设定滚动时间间隔    searchRequest.scroll(scroll);    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();    searchSourceBuilder.query(matchAllQuery());    searchSourceBuilder.size(5); //设定每次返回多少条数据    searchRequest.source(searchSourceBuilder);    log.info("string:" + searchRequest.source());    SearchResponse searchResponse = null;    try {        searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);    } catch (IOException e) {        e.printStackTrace();    }    String scrollId = searchResponse.getScrollId();    SearchHit[] searchHits = searchResponse.getHits().getHits();    System.out.println("-----首页-----");    for (SearchHit searchHit : searchHits) {        System.out.println(searchHit.getSourceAsString());    }    //遍历搜索命中的数据,直到没有数据    while (searchHits != null && searchHits.length > 0) {        SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);        scrollRequest.scroll(scroll);        log.info("string:" + scrollRequest.toString());        try {            searchResponse = restHighLevelClient.scroll(scrollRequest, RequestOptions.DEFAULT);        } catch (IOException e) {            e.printStackTrace();        }        scrollId = searchResponse.getScrollId();        searchHits = searchResponse.getHits().getHits();        if (searchHits != null && searchHits.length > 0) {            System.out.println("-----下一页-----");            for (SearchHit searchHit : searchHits) {                System.out.println(searchHit.getSourceAsString());            }        }​    }        //清除滚屏    ClearScrollRequest clearScrollRequest = new ClearScrollRequest();    clearScrollRequest.addScrollId(scrollId);//也可以选择setScrollIds()将多个scrollId一起使用    ClearScrollResponse clearScrollResponse = null;    try {        clearScrollResponse = restHighLevelClient.clearScroll(clearScrollRequest,RequestOptions.DEFAULT);    } catch (IOException e) {        e.printStackTrace();    }    boolean succeeded = clearScrollResponse.isSucceeded();    System.out.println("succeeded:" + succeeded);}

演示用例:com.qianfeng.elasticsearch.test.document.testIdsQuery

@Testpublic void testScrollQuery() throws IOException {    baseQuery.scrollQuery(indexName,type);}

演示效果:

721e2a097b411aff4e37c364748e5b2b.png

源码地址:https://github.com/qfjiaoyan/elasticsearch-examples

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值