java 调用 es restful api 使用 scroll 查询索引的全部数据

需求

  查询某个索引的全部数据,用于导出

什么是 scroll 查询

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

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

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

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

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

解释来自 https://www.elastic.co/guide/cn/elasticsearch/guide/2.x/scroll.html

具体使用

public static void exportExcel(String ip, String name, String type) throws HttpProcessException, IOException {
        // 请求体,查询条件
        JSONObject jsonObject = JSONUtil.parseObj(json);
        jsonObject.putOpt("size", 10000);
        HttpConfig config = HttpConfig.custom()
                .url("http://" + ip + ":9200/" + name + "/" + type + "/_search?scroll=1m")
                .json(jsonObject.toString());

        String response = HttpClientUtil.post(config);

        //解析查询结果
        JSONObject object = JSONUtil.parseObj(response);
        if (response.contains("error")) {
            String reason = object.getJSONObject("error").getStr("reason");
            return;
        }
        
        // 获取本次查询的 scroll_id,后续查询带上这个 id 即可
        String scroll_id = object.getStr("_scroll_id");
        JSONObject hits = object.getJSONObject("hits");

        // 结果集
        JSONArray hitsArray = hits.getJSONArray("hits");
        List<JSONObject> hitsList = hitsArray.toList(JSONObject.class);
        JSONObject scroll = new JSONObject();
        scroll.putOpt("scroll_id", scroll_id);
        scroll.putOpt("scroll", "2m");

        // 循环
        while (hitsList.size() != 0) {

            // 这里填写你的业务逻辑,即对每一条数据的处理


            // 继续向后查询
            config = HttpConfig.custom()
                    .url("http://" + ip + ":9200/_search/scroll")
                    .json(JSONUtil.toJsonStr(scroll));
            object = JSONUtil.parseObj(HttpClientUtil.post(config));
            hits = object.getJSONObject("hits");
            // 结果集
            hitsArray = hits.getJSONArray("hits");
            hitsList = hitsArray.toList(JSONObject.class);
        }
    }
posted @ 2020-09-01 10:55  正在路上的兔子  阅读(2264)  评论(0编辑  收藏  举报