欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ES的滚动搜索

程序员文章站 2022-03-11 09:12:16
游标查询Scroll滚动搜索API,即Search Scroll API,可通过搜索请求,获取大量搜索结果。滚动搜索有点类似于数据库中的分页查询。ES对于from+size的个数是有限制的,二者之和不能超过1w。当所请求的数据总量大于1w时,可用scroll来代替from+size。如果一次性要查出来比如10万条数据,那么性能会很差,此时一般会采取用scoll滚动查询,一批一批的查,直到所有数据都查询完处理完。scroll查询 可以用来对 Elasticsearch 有效地执行大批量.....

游标查询 Scroll

滚动搜索API,即Search Scroll API,可通过搜索请求,获取大量搜索结果。滚动搜索有点类似于数据库中的分页查询。

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

如果一次性要查出来比如10万条数据,那么性能会很差,此时一般会采取用scoll滚动查询,一批一批的查,直到所有数据都查询完处理完。

scroll 查询 可以用来对 Elasticsearch 有效地执行大批量的文档查询,而又不用付出深度分页那种代价。

游标查询允许我们 先做查询初始化,然后再批量地拉取结果。 这有点儿像传统数据库中的 cursor 。

游标查询会取某个时间点的快照数据。 查询初始化之后索引上的任何变化会被它忽略。 它通过保存旧的数据文件来实现这个特性,结果就像保留初始化时的索引 视图 一样。

深度分页的代价根源是结果集全局排序,如果去掉全局排序的特性的话查询结果的成本就会很低。 游标查询用字段 _doc 来排序。 这个指令让 Elasticsearch 仅仅从还有结果的分片返回下一批结果。

启用游标查询可以通过在查询的时候设置参数 scroll 的值为我们期望的游标查询的过期时间。 游标查询的过期时间会在每次做查询的时候刷新,所以这个时间只需要足够处理当前批的结果就可以了,而不是处理查询结果的所有文档的所需时间。 这个过期时间的参数很重要,因为保持这个游标查询窗口需要消耗资源,所以我们期望如果不再需要维护这种资源就该早点儿释放掉。 设置这个超时能够让 Elasticsearch 在稍后空闲的时候自动释放这部分资源。

GET /old_index/_search?scroll=1m 
{
    "query": { "match_all": {}},
    "sort" : ["_doc"], 
    "size":  1000
}

ES的滚动搜索

保持游标查询窗口一分钟。

ES的滚动搜索

关键字 _doc 是最有效的排序顺序。

这个查询的返回结果包括一个字段 _scroll_id`, 它是一个base64编码的长字符串 ((("scroll_id"))) 。 现在我们能传递字段 `_scroll_id 到 _search/scroll 查询接口获取下一批结果:

GET /_search/scroll
{
    "scroll": "1m", 
    "scroll_id" : "cXVlcnlUaGVuRmV0Y2g7NTsxMDk5NDpkUmpiR2FjOFNhNnlCM1ZDMWpWYnRROzEwOTk1OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MTA5OTM6ZFJqYkdhYzhTYTZ5QjNWQzFqVmJ0UTsxMTE5MDpBVUtwN2lxc1FLZV8yRGVjWlI2QUVBOzEwOTk2OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MDs="
}

ES的滚动搜索

注意再次设置游标查询过期时间为一分钟。

这个游标查询返回的下一批结果。 尽管我们指定字段 size 的值为1000,我们有可能取到超过这个值数量的文档。 当查询的时候, 字段 size 作用于单个分片,所以每个批次实际返回的文档数量最大为 size * number_of_primary_shards 。

注意游标查询每次返回一个新字段 _scroll_id`。每次我们做下一次游标查询, 我们必须把前一次查询返回的字段 `_scroll_id 传递进去。 当没有更多的结果返回的时候,我们就处理完所有匹配的文档了。

使用ES高级客户端实现:

    /**
     * 滚动搜索
     *
     * @return
     */
    public String scroll() {
        // 步骤一  初始化滚动搜索的上下文信息。 ------------------------------
        // 构建滚动搜索请求
        SearchRequest searchRequest = new SearchRequest("secisland");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("detail", "IPS面板"));
        // 设置单分片查询的数量
        searchSourceBuilder.size(10);
        searchRequest.source(searchSourceBuilder);

        // 设置滚动间隔
        searchRequest.scroll(TimeValue.timeValueMillis(1L));

        try {
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            // 步骤二 检索所有相关文档。 ---------------------------
            // 滚动搜索id
            String scrollId = searchResponse.getScrollId();
            // 文档
            SearchHits hits = searchResponse.getHits();
            while (hits != null && hits.getHits().length != 0) {
                // 设置滚动标识符
                SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
                scrollRequest.scroll(TimeValue.timeValueSeconds(30));
                SearchResponse searchResponse1 = restHighLevelClient.scroll(scrollRequest, RequestOptions.DEFAULT);

                // 读取新的scrollId
                scrollId = searchResponse1.getScrollId();
                // 读取新的hits
                hits = searchResponse1.getHits();
            }
            System.out.println("结果" + searchResponse);
        } catch (IOException e) {
            System.out.println("执行失败" + e.getMessage());
        }

        return null;
    }

以上代码分为两个步骤实现滚动搜索。

步骤1:初始化滚动搜索的上下文信息。

在执行滚动搜索API时,滚动搜索会话的初始化必须带有滚动搜索参数的搜索请求,即SearchRequest。在执行该搜索请求时,Elasticsearch会检测到滚动搜索参数的存在,并在相应的时间间隔内保持搜索上下文活动。

步骤2:检索所有相关文档。

首先在SearchScrollRequest中设置上文提及的滚动标识符和新的滚动间隔;其次在设置好SearchScrollRequest后,将其传送给searchScroll方法。在请求发出后,Elasticsearch服务器会返回另一批带有新的滚动标识符的结果。依次类推,用户需要在新的SearchScrollRequest中设置前文提及的滚动标识符和新的滚动间隔,以便获取下一批次的结果。这个过程会在一个循环中重复执行,直到不再有任何结果返回。这意味着滚动搜索已经完成,所有匹配的文档都已被检索。

SearchScrollRequest的可选参数

在SearchScrollRequest中,除滚动标识符外,还提供了可选参数供用户进行配置。SearchScrollRequest提供的主要可选参数是滚动搜索的过期时间,代码如下所示:

ES的滚动搜索

在实际开发中,如果读者没有为SearchScrollRequest设置滚动标识符,则一旦初始滚动时间过期(即初始搜索请求中设置的滚动时间过期),则滚动搜索的上下文也会过期。

清除滚动搜索的上下文

在滚动搜索请求执行后,用户可以使用Clear Scroll API删除最后一个滚动标识符,以释放滚动搜索的上下文。当滚动搜索超时时间到期时,这个过程也会自动发生。一般在滚动搜索会话后,需立即清除滚动搜索的上下文。在执行清除滚动搜索上下文的请求之前,需要构建清除滚动搜索请求,即ClearScrollRequest。ClearScrollRequest需要把滚动标识符作为参数输入,构建ClearScrollRequest的代码如下所示:

ES的滚动搜索

在构建ClearScrollRequest时,不仅可以配置单个滚动标识符,还可以配置多个滚动标识符。我们继续在上述方法中添加如下代码:

ES的滚动搜索

执行清除滚动搜索请求在ClearScrollRequest构建后,即可执行清除滚动搜索请求了。与文档索引请求类似,清除滚动搜索请求也有同步和异步两种执行方式。这里就不细说看,跟之前的一样。

ES的滚动搜索

 

本文地址:https://blog.csdn.net/weixin_40663800/article/details/110947725

相关标签: ES