Java实现Elasticsearch查询当前索引全部数据的完整代码

本文主要是介绍Java实现Elasticsearch查询当前索引全部数据的完整代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Java实现Elasticsearch查询当前索引全部数据的完整代码》:本文主要介绍如何在Java中实现查询Elasticsearch索引中指定条件下的全部数据,通过设置滚动查询参数(scrol...

需求背景

通常情况下,Elasticsearch 为了提高查询效率,对于不指定分页查询条数的查询语句,默认会返回10条数据。那么这就会有一种情况,当你需要一次性返回 Elasticsearch 索引中的全部数据时,就无法实现了。这个时候你可能会考虑,比如我将每页取值的size 设置的很大,这样或许可以解决问题,但是数据量的上升你是无法控制的,最终会有一天数据量会超过你此时设置的最大 size,那么这就是一个雷点。并且如果一次查询很大量数据的话,即便是 Elasticsearch 查询效率高的索引结构可能也会导致查询时长较长,甚至响应超时。那么是否有一种查询效率高,且相对灵活的方式可以查询 Elasticsearch 的索引中全部数据呢?答案是:有的。

通常情况

下面来看一下在不设置 size 大小的情况下,执行 Elasticsearch 查询语句默认返回几条数据,结果是默认返回 10条。执行如下查询命令

GET crm_meiqia_conversation/_search

返回结果如图,这时我们看到返回了 10 条数据

Java实现Elasticsearch查询当前索引全部数据的完整代码

此时如果你需要查询更多数据的话,你就可以通过指定 size 大小来查询更多数据,比如执行如下命令

GET crm_meiqia_conversation/_search
{
  "size":20
}

执行查询语句后返回的结果如图所示,索引查询会返回你指定 size 大小的数据

Java实现Elasticsearch查询当前索引全部数据的完整代码

很明显,在一些特殊的场景下,想要一次性查询指定条件下的所有数据改如何操作呢,下面就来基于 Java 实现查询指定条件下的所有数据操作。

Java 实现查询 Elasticsearch 全部数据

在具体讲解如何通过 Java 实现查询 Elasticsearch 全部数据之前,我们可以先来看一下我已经实现之后的查询效果。这里你可以看到滚动州已经变得很小,这就是因为我查询出了指定条件下的全部数据导致的,而不是默认的 10 条数据

Java实现Elasticsearch查询当前索引全部数据的完整代码

而如果没有实现查询指定索引指定条件下的全部数据时,看到的效果应该是这样的,默认只能一次性查询 10 条数据返回

Java实现Elasticsearch查询当前索引全部数据的完整代码

下面再来讲一下如何通过 Java 实现 查询 es 全部数据,我们由浅入深来讲解,首先来看一下默认查询 es 10条数据的代码,Java 通过如下 SearchRequestBuilder searchRequest = client.prepareSearch(indexProperties.getMeiqiaConversationIndex()).setTypes(indexProperties.getMeiqiaConversationType()).setQuery(query); 构造查询 es 索引代码,这种情况没有设置 size 大小,默认的话就是查询指定索引下 10条数据,完整代码如下:

public AJAXResult getMeiqiaUidList(MeiqiaConversation meiqiaConversation) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //会话id
        Long convId = meiqiaConversation.getConvId();
        if (convId != null) {
            boolQuery.filter(QueryBuilders.termQuery("convId",convId));
        }
        //会话日期
        String convStartDate = (String) meiqiaConversation.getParams().get("convStartDate");
        String convEndDate = (String) meiqiaConversation.getParams().get("convEndDate");
        if (StringUtils.isNotEmpty(convStartDate)) {
            Date date = DateUtils.stringToDate(convStartDate, DateUtils.SDF_YMDHMS);
            boolQuery.filter(QueryBuilders.rangeQuery("convStartDate").gte(date.getTime()));
        }
        if (StringUtil.isNotEmptyString(convEndDate)) {
            Date date = DateUtils.stringToDate(convEndDate, DateUtils.SDF_YMDHMS);
            boolQuery.filter(QueryBuilders.rangeQuery("convEndDate").lte(date.getTime()));
        }
        //会话日期
        Date convStartDate2 = meiqiaConversation.getConvStartDate();
        Date convEndDate2 = meiqiaConversation.getConvEndDate();
        if (Objects.nonNull(convStartDate2)) {
            boolQuery.filter(QueryBuilders.rangeQuery("convStartDate").gte(convStartDate2.getTime()));
        }
        if (Objects.nonNull(convEndDate2)) {
            boolQuery.filter(QueryBuilders.rangeQuery("convEndDate").lte(convEndDate2.getTime()));
        }
        //学号
        String uid = (String) meiqiaConversation.getParams().get("uid");
        if (StringUtils.isNotEmpty(uid)) {
            if (uid.contains("#")) {
                String replace = uid.replace("#", "");
                boolQuery.filter(QueryBuilders.termQuery("clientInfo.name",replace));
            }else {
                boolQuery.filter(QueryBuilders.termQuery("clientInfo.uid",uid));
            }
        }
        //客服工号
        String agentId = (String) meiqiaConversation.getParams().get("agentId");
        if (StringUtils.isNotEmpty(agentId)) {
            boolQuery.filter(QueryBuilders.termQuery("agentId",agentId));
        }
        // 会话内容
        String content = (String) meiqiaConversation.getParams().get("content");
        if (StringUtils.isNotEmpty(content)) {
            boolQuery.filter(QueryBuilders.matchPhrasePrefixQuery("convContent.content",content));
        }

        query.must(boolQuery);

        // 初始化搜索请求构建器,用于构造搜索请求
        SearchRequestBuilder searchRequest = client.prepareSearch(indexProperties.getMeiqiaConversationIndex())
                // 设置搜索的类型
                .setTypes(indexProperties.getMeiqiaConversationType())
                // 设置查询条件
                .setQuery(query);


        // 使用SearchRequest获取搜索响应
        SearchResponse searchResponse = searchRequest.get();
        // 初始化存储所有搜索结果的列表
        List<EsMeiqiaConversation> rows = new ArrayList<>();
        // 格式化搜索响应中的数据,并添加到rows列表中
        List<EsMeiqiaConversation> list1 = formatMeiqiaDto(searchResponse);
        rows.addAll(list1);


        //记录返回的uid name
        List<MeiqiaConversation> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(rows)) {
            //获取 uid name
            Map<String, List<EsMeiqiaConversation>> collect = rows.stream().collect(Collectors.groupingBy(EsMeiqiaConversation::getClientUid, Collectors.toList()));
            Set<String> uids = collect.keySet();
            for (String u : uids) {
                MeiqiaConversation conv = new MeiqiaConversation();
                conv.setUid(u);
                //同一个uid 对应同一个 name
                List<EsMeiqiaConversation> esconv = collect.get(u);
                String name = esconv.get(0).getClientName();
                conv.setName(name);
                list.add(conv);
            }
        }
        return AjaxResult.success(list);
    android}

那么如何实现 一次查询满足条件的全部 es 数据呢,这就需要通过 scroll 实现,在初始化索引查询构造器时通过 SearchRequestBuilder searchRequest = client.prepareSearch(indexProperties.getMeiqiaConversationIndex()).setTypes(indexProperties.getMeiqiaConversationType()).setQuery(query).setSize(100).setScroll(TimeValue.timeValueMinutes(1)); 设置 scroll 参数来实现,同时需要再后续增加再次查询索引逻辑,将 scorllId 循环传递 获取全部数据,最终改造后的获取全部数据的代码如下

    public AjaxResult getMeiqiaUidList(MeiqiaConversation meiqiaConversation) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //会话id
        Long convId = meiqiaConversation.getConvId();
        if (convId != null) {
            boolQuery.filter(QueryBuilders.termQuery("convId",convId));
        }
        //会话日期
        String convStartDate = (String) meiqiaConversation.getParams().get("convStartDate");
        String convEndDate = (String) meiqiaConversation.getParams().get("convEndDateandroid");
        if (StringUtils.isNotEmpty(convStartDate)) {
            Date date = DateUtils.stringToDate(convStartDate, DateUtils.SDF_YMDHMS);
            boolQuery.filter(QueryBuilders.rangeQuery("convStartDate").gtehttp://www.chinasem.cn(date.getTime()));
        }
        if (StringUtil.isNotEmptyString(convEndDate)) {
            Date date = DateUtils.stringToDate(convEndDate, DateUtils.SDF_YMDHMS);
            boolQuery.filter(QueryBuilders.rangeQuery("convEndDate").lte(date.getTime()));
        }
        //会话日期
        Date convStartDate2 = meiqiaConversation.getConvStartDate();
        Date convEndDate2 = meiqiaConversation.getConvEndDate();
        if (Objects.nonNull(convStartDate2)) {
            boolQuery.filter(QueryBuilders.rangeQuery("convStartDate").gte(convStartDate2.getTime()));
        }
        if (Objects.nonNull(convEndDate2)) {
            boolQuery.filter(QueryBuilders.rangeQuery("convEndDate").lte(convEndDate2.getTime()));
        }
        //学号
        String uid = (String) meiqiaConversation.getParams().get("uid");
        if (StringUtils.isNotEmpty(uid)) {
            if (uid.contains("#")) {
                String replace = uid.replace("#", "");
                boolQuery.filter(QueryBuilders.termQuery("clientInfo.name",replace));
            }else {
                boolQuery.filter(QueryBuilders.termQuery("clientInfo.uid",uid));
            }
        }
        //客服工号
        String agentId = (String) meiqiaConversation.getParams().get("agentId");
        if (StringUtils.isNotEmpty(agentId)) {
            boolQuery.filter(QueryBuilders.termQuery("agentId",agentId));
        }
        // 会话内容
        String content = (String) meiqiaConversation.getParams().get("content");
        if (StringUtils.isNotEmpty(content)) {
            boolQuery.filter(QueryBuilders.matchPhrasePrefixQuery("convContent.content",content));
        }

        query.must(boolQuery);

        // 初始化搜索请求构建器,用于构造搜索请求
        SearchRequestBuilder searchRequest = client.prepareSearch(ipythonndexProperties.getMeiqiaConversationIndex())
                // 设置搜索的类型
                .setTypes(indexProperties.getMeiqiaConversationType())
                // 设置查询条件
                .setQuery(query)
                // 设置返回结果的数量为100
                .setSize(100)
                // 设置滚动查询的时间间隔为1分钟
                .setScroll(TimeValue.timeValueMinutes(1));

        // 使用SearchRequest获取搜索响应
        SearchResponse searchResponse = searchRequest.get();
        // 初始化存储所有搜索结果的列表
        List<EsMeiqiaConversation> rows = new ArrayList<>();
        // 格式化搜索响应中的数据,并添加到rows列表中
        List<EsMeiqiaConversation> list1 = formatMeiqiaDto(searchResponse);
        rows.addAll(list1);
        // 使用Scroll方式遍历所有搜索结果
        do {
            // 准备下一次Scroll搜索,设置滚动时间为1分钟
            // 将scorllId循环传递 获取全部数据
            searchResponse = client.prepareSearchScroll(searchResponse.getScrollId()).setScroll(TimeValue.timeValueMinutes(1)).execute().actionGet();
            // 格式化新一批搜索结果,并添加到rows列表中
            List<EsMeiqiaConversation> list = formatMeiqiaDto(searchResponse);
            if (CollectionUtils.isNotEmpty(list)) {
                rows.addAll(list);
            }
            // 当搜索结果为空时,结束循环
            // 当searchHits的数组为空的时候结束循环,至此数据全部读取完毕
        } while (searchResponse.getHits().getHits().length != 0);

        // 创建一个ClearScrollRequest实例,用于清除滚动查询的会话。
        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();

        // 将上一次查询返回的滚动ID添加到请求中,以便清除这个特定的会话。
        // 这是必要的,因为ClearScrollRequest需要至少一个滚动ID才能执行清除操作。
        clearScrollRequest.addScrollId(searchResponse.getScrollId());

        // 发送ClearScroll请求并获取操作的结果。
        // 这一步是必需的,因为它实际执行了清除滚动会话的操作,并允许我们处理结果或任何异常。
        client.clearScroll(clearScrollRequest).actionGet();

        //记录返回的uid name
        List<MeiqiaConversation> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(rows)) {
            //获取 uid name
            Map<String, List<EsMeiqiaConversation>> collect = rows.stream().collect(Collectors.groupingBy(EsMeiqiaConversation::getClientUid, Collectors.toList()));
            Set<String> uids = collect.keySet();
            for (String u : uids) {
                MeiqiaCojavascriptnversation conv = new MeiqiaConversation();
                conv.setUid(u);
                //同一个uid 对应同一个 name
                List<EsMeiqiaConversation> esconv = collect.get(u);
                String name = esconv.get(0).getClientName();
                conv.setName(name);
                list.add(conv);
            }
        }
        return AjaxResult.success(list);
    }

那么这段的核心代码是增加了滚动查询数据的操作,如图所示

Java实现Elasticsearch查询当前索引全部数据的完整代码

同时再执行循环查询时将 scrollId 循环传递,并将查询结果 addAll 到当前list 的集合中

Java实现Elasticsearch查询当前索引全部数据的完整代码

查询结束之后,最后是清除滚动会话的操作

Java实现Elasticsearch查询当前索引全部数据的完整代码

到这里关于 Java 实现 es 查询指定条件下的全部数据操作就结束了,整个操作过程比较容易理解,增加了 es 滚动查询 scroll 操作来实现查询 es 全部数据。

写在最后

最后想要说的是,对于 es 查询,通常情况下是不需要一次性查询出当前索引所有条件下的数据的,毕竟数据量比较大,但是也有特殊的场景,这个时候不得不一次性查询出所有的数据,这就需要上文中用到的办法了,希望对大家有帮助。

到此这篇关于Java实现Elasticsearch查询当前索引全部数据的文章就介绍到这了,更多相关Java Elasticsearch查询当前索引全部数据内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于Java实现Elasticsearch查询当前索引全部数据的完整代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153324

相关文章

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

java中新生代和老生代的关系说明

《java中新生代和老生代的关系说明》:本文主要介绍java中新生代和老生代的关系说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、内存区域划分新生代老年代二、对象生命周期与晋升流程三、新生代与老年代的协作机制1. 跨代引用处理2. 动态年龄判定3. 空间分

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析