Java 实现 Elasticsearch 查询全部数据

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 【7月更文挑战第7天】Java 实现 Elasticsearch 查询全部数据

背景信息

es查询,在不指定 size 大小的情况下,默认查询 10条数据,比如执行如下查询命令

GET crm_meiqia_conversation/_search

image.png

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

GET crm_meiqia_conversation/_search
{
  "size":20
}

image.png

这个时候就有个疑问,如果有一些特殊的场景,想要一次性查询指定条件下的所有数据改如何操作呢,下面就来基于 Java 实现查询指定条件下的所有数据操作。

Java 实现查询 Elasticsearch 全部数据

实现后效果

首先来看一下基于 Java 实现查询指定条件下的 es 所有数据的展示效果

image.png

实现前效果

而默认情况下不设置 size 大小的 es 查询,默认查询 10条数据,就像这样的效果

image.png

Java 代码实现

下面开始讲如何通过 Java 实现查询 es 全部数据,首先来看一下默认查询 es 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);
    }

那么如何实现 一次查询满足条件的全部 es 数据呢,可以通过 scroll 实现,改造后的代码如下

    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)
                // 设置返回结果的数量为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) {
                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);
    }

核心代码是增加了滚动查询数据的操作

image.png

image.png

最后是清除滚动会话的操作

image.png

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

写在最后

以上是实现 es 查询指定条件下的全部数据的代码方法,大家需要借鉴的话,只需要补充 滚动查询部分即可,希望对大家有帮助。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
7天前
|
Java 程序员 容器
Java中的变量和常量:数据的‘小盒子’和‘铁盒子’有啥不一样?
在Java中,变量是一个可以随时改变的数据容器,类似于一个可以反复打开的小盒子。定义变量时需指定数据类型和名称。例如:`int age = 25;` 表示定义一个整数类型的变量 `age`,初始值为25。 常量则是不可改变的数据容器,类似于一个锁死的铁盒子,定义时使用 `final` 关键字。例如:`final int MAX_SPEED = 120;` 表示定义一个名为 `MAX_SPEED` 的常量,值为120,且不能修改。 变量和常量的主要区别在于变量的数据可以随时修改,而常量的数据一旦确定就不能改变。常量主要用于防止意外修改、提高代码可读性和便于维护。
|
26天前
|
存储 Java API
深入剖析Java Map:不只是存储数据,更是设计艺术的体现!
【10月更文挑战第17天】在Java编程中,Map是一种重要的数据结构,用于存储键值对,并展现了设计艺术的精髓。本文深入剖析了Map的设计原理和使用技巧,包括基本概念、设计艺术(如哈希表与红黑树的空间时间权衡)、以及使用技巧(如选择合适的实现类、避免空指针异常等),帮助读者更好地理解和应用Map。
80 3
|
7天前
|
存储 缓存 安全
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见。本文介绍了使用 `File.createTempFile` 方法和自定义创建临时文件的两种方式,详细探讨了它们的使用场景和注意事项,包括数据缓存、文件上传下载和日志记录等。强调了清理临时文件、确保文件名唯一性和合理设置文件权限的重要性。
19 2
|
7天前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
15 2
|
12天前
|
存储 分布式计算 Java
存算分离与计算向数据移动:深度解析与Java实现
【11月更文挑战第10天】随着大数据时代的到来,数据量的激增给传统的数据处理架构带来了巨大的挑战。传统的“存算一体”架构,即计算资源与存储资源紧密耦合,在处理海量数据时逐渐显露出其局限性。为了应对这些挑战,存算分离(Disaggregated Storage and Compute Architecture)和计算向数据移动(Compute Moves to Data)两种架构应运而生,成为大数据处理领域的热门技术。
33 2
|
17天前
|
SQL Java OLAP
java实现“数据平滑升级”
java实现“数据平滑升级”
35 2
|
22天前
|
SQL Java 关系型数据库
java连接mysql查询数据(基础版,无框架)
【10月更文挑战第12天】该示例展示了如何使用Java通过JDBC连接MySQL数据库并查询数据。首先在项目中引入`mysql-connector-java`依赖,然后通过`JdbcUtil`类中的`main`方法实现数据库连接、执行SQL查询及结果处理,最后关闭相关资源。
|
27天前
|
Java
Java Set以其“不重复”的特性,为我们提供了一个高效、简洁的处理唯一性约束数据的方式。
【10月更文挑战第16天】在Java编程中,Set接口确保集合中没有重复元素,每个元素都是独一无二的。HashSet基于哈希表实现,提供高效的添加、删除和查找操作;TreeSet则基于红黑树实现,不仅去重还能自动排序。通过这两个实现类,我们可以轻松处理需要唯一性约束的数据,提升代码质量和效率。
34 2
|
19天前
|
SQL Java OLAP
java实现“数据平滑升级”
java实现“数据平滑升级”
10 0
|
前端开发 安全 Java
面试官:java8中parallelStream提升数倍查询效率是怎样实现的
业务场景 在很多项目中,都有类似数据汇总的业务场景,查询今日注册会员数,在线会员数,订单总金额,支出总金额等。。。这些业务通常都不是存在同一张表中,我们需要依次查询出来然后封装成所需要的对象返回给前端。那么在此过程中,就可以把这个接口中“大任务”拆分成N个小任务,异步执行这些小任务,等到最后一个小任务执行完,把所有任务的执行结果封装到返回结果中,统一返回到前端展示。
面试官:java8中parallelStream提升数倍查询效率是怎样实现的