Easy-Es Easy-Es
💋首页
  • v3.0.0(当前版本)
  • What's New

    • What' s New In Easy-Es v3.0.0?
  • 历史版本

    • v1.x.x
    • v2.x.x
  • 升级指南

    • 升级到3.x.x说明
💖赞助
  • 开源社区
  • 周边好物
  • 项目PPT (opens new window)
  • 项目介绍
  • 项目成员
  • 参与贡献
加入社区讨论
谁在使用
  • Doc-Apis (opens new window)
  • 健身计划一键生成系统 (opens new window)
  • 极氪汽车
  • Vuepress-theme-vdoing (opens new window)
  • Gitee (opens new window)
  • GitCode (opens new window)
  • Github (opens new window)
  • 简体中文 (opens new window)
  • English (opens new window)

广告采用随机轮播方式显示 ❤️成为赞助商
💋首页
  • v3.0.0(当前版本)
  • What's New

    • What' s New In Easy-Es v3.0.0?
  • 历史版本

    • v1.x.x
    • v2.x.x
  • 升级指南

    • 升级到3.x.x说明
💖赞助
  • 开源社区
  • 周边好物
  • 项目PPT (opens new window)
  • 项目介绍
  • 项目成员
  • 参与贡献
加入社区讨论
谁在使用
  • Doc-Apis (opens new window)
  • 健身计划一键生成系统 (opens new window)
  • 极氪汽车
  • Vuepress-theme-vdoing (opens new window)
  • Gitee (opens new window)
  • GitCode (opens new window)
  • Github (opens new window)
  • 简体中文 (opens new window)
  • English (opens new window)
  • 快速入门

    • 简介
    • 适用场景
    • 顾虑粉碎
    • 避坑指南
    • 快速开始
    • springboot集成demo
    • spring集成指南
    • solon集成指南
    • 配置
    • 注解
  • 核心功能

    • 条件构造器

      • 条件构造器介绍
      • 索引条件构造器
      • 查询条件构造器
      • 更新条件构造器
    • 索引CRUD

      • 索引托管模式
      • 索引CRUD
    • 数据CRUD

      • 数据同步方案
      • 数据CRUD
    • 多数据源支持
    • 动态索引支持
    • 四大嵌套查询
    • 链式调用
  • 拓展功能

    • 混合查询
    • 原生查询
    • 分页查询
    • 嵌套类型
    • Join父子类型
    • 获取DSL语句
    • 执行DSL语句
    • 执行SQL语句
    • 自定义RequestOptions
    • 自定义default方法
  • 高阶语法

    • 查询字段过滤
    • 排序
    • 聚合查询
      • 常规聚合
      • 其它聚合:
      • 去重聚合
    • 分词&模糊匹配
    • 权重
    • 高亮查询
    • GEO地理位置查询
    • IP查询
  • 插件

    • 插件
    • 领域模型生成插件
  • 其它

    • 问答
    • 与MP差异
    • MySQL和EE语法对比
    • 更新日志
    • 更新计划
    • 版权
    • 鸣谢
  • v2.x文档
  • 高阶语法
老汉
2023-03-18
目录

聚合查询

前言

聚合可以算得上ES中最难用的一部分了,其API也是最反人类的,懂的都懂。对聚合的支持,SpringData-ElasticSearch直接放弃了,EE对其ES的聚合的简化也比较有限,尽管如此,也算得上目前市面上开源框架中对ES聚合支持得最好的框架了,大家在用得时候请轻喷,在聚合方式排列组合有上千种,以及灵活多变的树形桶得数据解析上,我们真的尽力了,奉劝大家抛弃幻想,准备迎接挑战,这不是MySQL。ES的聚合和MySQL的Group By聚合完全是两种不同的东西。 您现在看到的聚合也绝对不是EE对聚合支持的最终形态,我们还会持续探索进一步简化聚合,来减轻用户使用ES聚合功能的烦恼。

# 常规聚合

在MySQL中,我们可以通过指定字段进行group by聚合,EE同样也支持类似聚合:

    @Test
    public void testGroupBy() {
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.likeRight(Document::getContent,"推");
        wrapper.groupBy(Document::getCreator);
        // 支持多字段聚合
        // wrapper.groupBy(Document::getCreator,Document::getCreator);
        SearchResponse response = documentMapper.search(wrapper);
        System.out.println(response);
    }
1
2
3
4
5
6
7
8
9
10

设置聚合桶大小及桶内排序

    @Test
    @Order(6)
    public void testConditionGroupBy() {
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.match(Document::getContent, "测试")
                .size(20) // 设置聚合桶大小
                .bucketOrder(BucketOrder.count(Boolean.TRUE)) // 设置桶排序规则
                .groupBy(Document::getStarNum);
        SearchResponse response = documentMapper.search(wrapper);
        System.out.println(response);
    }
1
2
3
4
5
6
7
8
9
10
11

温馨提示

尽管语法与MP一致,但实际上,ES的聚合结果是放在单独的对象中的,格式如下所示,因此我们高阶语法均需要用SearchResponse来接收返回结果,这点需要区别于MP和MySQL.

"aggregations":{"sterms#creator":{"doc_count_error_upper_bound":0,"sum_other_doc_count":0,"buckets":[{"key":"老汉","doc_count":2},{"key":"老王","doc_count":1}]}}
1

# 其它聚合:

// 求最小值
wrapper.min();
// 求最大值
wrapper.max();
// 求平均值
wrapper.avg();
// 求和
wrapper.sum();
1
2
3
4
5
6
7
8

如果需要先groupBy,再根据groupBy聚合后桶中的数据进行求最值,均值之类的,也是支持的,会按照您在wrapper中指定的顺序,管道聚合(pipeline aggregation).

示例:

    @Test
    public void testAgg() {
        // 根据创建者聚合,聚合完在该桶中再次根据点赞数聚合
        // 注意:指定的多个聚合参数为管道聚合,就是第一个聚合参数聚合之后的结果,再根据第二个参数聚合,对应Pipeline聚合
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.eq(Document::getTitle, "老汉")
                .groupBy(Document::getCreator)
                .max(Document::getStarNum);
        SearchResponse response = documentMapper.search(wrapper);
        System.out.println(response);
    }
1
2
3
4
5
6
7
8
9
10
11

另外EE还提供了可以配置是否开启管道聚合的参数,默认为开启,如果你想让多个字段聚合的结果出现在各自的桶中,那么你可以指定enablePipeline参数为false即可.

    @Test
    public void testAggNotPipeline() {
        // 对于下面两个字段,如果不想以pipeline管道聚合,各自聚合的结果在各自的桶中展示的话,我们也提供了支持
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        // 指定启用管道聚合为false
        wrapper.groupBy(false, Document::getCreator, Document::getTitle);
        SearchResponse response = documentMapper.search(wrapper);
        System.out.println(response);
    }
1
2
3
4
5
6
7
8
9

# 去重聚合

为了方便用户去重,我们针对字段的去重提供了极为友好的方式,解决用户根据字段进行去重及分页要写大量代码来实现的烦恼,使用ee单字段去重仅需1行即可搞定!

API:

    // 去重,入参为去重列
    wrapper.distinct(R column);
1
2

下面我用一段代码来演示根据指定字段去重:

    @Test
    public void testDistinct() {
        // 查询所有标题为老汉的文档,根据创建者去重,并分页返回
        LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.eq(Document::getTitle, "老汉")
                .distinct(Document::getCreator);
        PageInfo<Document> pageInfo = documentMapper.pageQuery(wrapper, 1, 10);
        System.out.println(pageInfo);
    }
1
2
3
4
5
6
7
8
9

坏味道

对于多字段的去重支持,没有上述这么简单,因为多字段去重无法通过折叠去实现,数据会被置入桶中返回,桶中数据的解析,需要哪些字段,排序规则,覆盖规则是怎样的过于灵活,我们无法通过框架来帮用户屏蔽这些,市面上目前也无任何框架能够支撑,因此,我们对多字段的去重仅支持到了查询条件的封装,数据解析部分需用户自行完成,敬请谅解.好在多字段去重的场景并不是太多,用户如果有用到多字段去重,可参见本篇开头对groupBy的介绍,可通过groupBy对多字段实现去重。

帮助我们改善此文档 (opens new window)
上次更新: 2025/05/11
排序
分词&模糊匹配

← 排序 分词&模糊匹配→

Theme by Vdoing | Copyright © 2021-2025 老汉 | 浙ICP备2022020479号 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式