添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
耍酷的墨镜  ·  Spring Data MongoDB ...·  1 周前    · 
讲道义的鞭炮  ·  springboot mongodb ...·  1 周前    · 
有情有义的橙子  ·  birdben·  1 周前    · 
高大的豆浆  ·  spark ...·  1 月前    · 
爱旅游的感冒药  ·  Maybe (RxJava Javadoc ...·  7 月前    · 

springboot mongodb 实现分组查询操作

如何在spring boot中使用mongodb实现group这样的分组统计查询呢?
比如: 统计中国每个省的同名人数 ,数据内容如下:

{ "country" : "china", "province" : "sh", "userid" : "a" }  
{  "country" : "china", "province" : "sh", "userid" : "b" } 
{  "country" : "china", "province" : "sh", "userid" : "c" }  
{  "country" : "china", "province" : "bj", "userid" : "da" }  
{  "country" : "china", "province" : "bj", "userid" : "fa" }  

统计结果为:[{"country" : "china", "province" : "sh", "count" : 3 },{"country" : "china", "province" : "bj", "count" : 2 }]
使用 aggregate([{ $group: {"_id": { "country" : "$country", "province": "$province" , "uid" : "$userid" } } } , { $group: {"_id": { "country" : "$_id.country", "province": "$_id.province" }, count : { $sum : 1 } } }]) mongdb正确获取到数据,那怎么使用java 在springboot中实现呢?

阅读 14.2k
2 个回答
得票 最新
头像
noel
110 6 14 25
✓ 已被采纳

使用聚合查询aggregation实现。由于mongodb数据库的特点,聚合使用到了 管道 操作。(PS. group 操作不能返回指定字段以外的其他字段)
类似的实现如下几步:

Aggregation agg = Aggregation.newAggregation(
                // 第一步:挑选所需的字段,类似select *,*所代表的字段内容
                Aggregation.project("licensePlate", "companyName", "deviceCode", "diverName", "fleet", "lineNumber",
                        "imgUrl", "videoUrl", "ptLoc", "locations"), 
                // 第二步:sql where 语句筛选符合条件的记录
                Aggregation.match(
                        Criteria.where("companyName").is(companyName).and("addedDate").gte(startTime).lte(endTime)), 
                // 第三步:分组条件,设置分组字段
                Aggregation.group("companyName", "licensePlate")
                        .count().as("allCount")// 增加COUNT为分组后输出的字段
                        .last("deviceCode").as("deviceCode").last("diverName").as("diverName").last("fleet").as("fleet")
                        .last("lineNumber").as("lineNumber").last("imgUrl").as("imgUrl").last("videoUrl").as("videoUrl")
                        .last("ptLoc").as("ptLoc").last("locations").as("locations"), // 增加publishDate为分组后输出的字段
                // 第四步:重新挑选字段
                Aggregation.project("diverName", "licensePlate", "companyName", "deviceCode", "allCount", "fleet",
                        "lineNumber", "imgUrl", "videoUrl", "ptLoc", "locations")
        AggregationResults<HeatMap> results = mongoOperations.aggregate(agg, "Historys", HeatMap.class);
        List<HeatMap> list = results.getMappedResults();

管道执行的性质,每一步按顺序执行,第一步操作结果传递给下一步进行才做,所以代码的顺序影响最后的结果,因此要想分组后获取集合其他字段,第一步和最后一步都要指定一下想要返回的字段。

头像
Reeye
310 7
    class User {
        private String country;
        private String province;
        private String name;
        public User(String country, String province, String name) {
            this.country = country;
            this.province = province;
            this.name = name;
        public String getCountry() {
            return country;
        public void setCountry(String country) {
            this.country = country;
        public String getProvince() {
            return province;
        public void setProvince(String province) {
            this.province = province;
        public String getName() {
            return name;
        public void setName(String name) {
            this.name = name;
    class Res {
        private String country;
        private String province;
        private Integer count;
        public Res(String country, String province, Integer count) {
            this.country = country;
            this.province = province;
            this.count = count;
        public String getCountry() {
            return country;
        public void setCountry(String country) {
            this.country = country;
        public String getProvince() {
            return province;
        public void setProvince(String province) {
            this.province = province;
        public Integer getCount() {
            return count;
        public void setCount(Integer count) {
            this.count = count;
    @Test
    public void test1() throws Exception {
        List<Res> result = new ArrayList<>();
        List<User> list = new ArrayList<>();
        list.add(new User("中国", "北京", "张三"));
        list.add(new User("中国", "北京", "张三"));
        list.add(new User("中国", "北京", "李四"));
        list.add(new User("中国", "北京", "李四"));
        list.add(new User("中国", "北京", "李四"));
        list.add(new User("中国", "北京", "王五"));
        list.add(new User("中国", "湖南", "张三"));
        list.add(new User("中国", "湖南", "张三"));
        list.add(new User("中国", "湖南", "张三"));
        list.stream()
                .collect(Collectors.groupingBy(e -> e.getProvince()))
                .forEach((k, v) -> {
                    StringBuilder count = new StringBuilder("0");
                    v.stream().
                            collect(Collectors.groupingBy(e -> e.getName()))
                            .forEach((k2, v2) -> {
                                if (v2.size() > 1) {
                                    int c = Integer.parseInt(count.toString());
                                    count.delete(0, count.length());
                                    count.append(c + v2.size());
                    result.add(new Res(v.get(0).getCountry(), v.get(0).getProvince(), Integer.parseInt(count.toString())));