• SpringBoot+mongodb实现分组统计、时间范围查询、去重排序查询、组合排序、分页查询


    SpringBoot+mongodb实现分组统计、时间范围查询、去重排序查询、组合排序

    目录

    一、分组统计(Aggregation)

    1.按某字段分组统计

        /**
         * 根据分类名称 分组统计销售数量
         * @param dataType 1:本日 2:本月 3:本年
         * @return
         */
        @RequestMapping("/findInfoByGroup")
        public List findInfoByGroup(){
            //从mongodb里获取满足条件的记录   status:状态 1:上架  2:下架
            Criteria criteria = Criteria.where("status").is(1);
            //聚合函数查询统计信息
            Aggregation aggregation = Aggregation.newAggregation(Aggregation.match(criteria),
                    //按分类名称 统计 销售数量
                    Aggregation.group("category").sum("sale_num").as("total"),
                    //按照total降序
                    Aggregation.sort(Sort.Direction.DESC,"total")
            );
            AggregationResults aggregationResults = mongoTemplate.aggregate(aggregation,Product.class,Map.class);
            List list = aggregationResults.getMappedResults();
    
            return list;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    category:要分组的字段
    sale_num:要统计的字段
    total:别名

    返回结果:

    [
        {
            "_id": "口红",
            "total": 2224.0
        },
        {
            "_id": "面膜",
            "total": 997.0
        },
        {
            "_id": "文具",
            "total": 799.0
        },
        {
            "_id": "男装",
            "total": 675.0
        },
        {
            "_id": "女装",
            "total": 448.0
        }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    _id本来应该是对应查询的字段,没有处理,spring会将分组字段自动转换为_id

    2.多字段分组统计

        /**
         * 根据分类名称和规格 分组统计销售数量
         * @param
         * @return
         */
        @RequestMapping("/findInfoByGroup1")
        public List findInfoByGroup1(){
            //从mongodb里获取最新的一条记录   status:状态 1:上架  2:下架
            Criteria criteria = Criteria.where("status").is(1);
            //聚合函数查询统计信息
            Aggregation aggregation = Aggregation.newAggregation(Aggregation.match(criteria),
                    //按分类名称 统计 销售数量
                    Aggregation.group("category","specification").sum("sale_num").as("total"),
                    //按照total降序
                    Aggregation.sort(Sort.Direction.DESC,"total")
            );
            AggregationResults aggregationResults = mongoTemplate.aggregate(aggregation,Product.class,Map.class);
            List list = aggregationResults.getMappedResults();
    
            return list;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    返回结果:

    [
        {
            "_id": {
                "category": "口红",
                "specification": "个"
            },
            "total": 2224.0
        },
        {
            "_id": {
                "category": "面膜",
                "specification": "盒"
            },
            "total": 997.0
        },
        {
            "_id": {
                "category": "文具",
                "specification": "套"
            },
            "total": 799.0
        },
        {
            "_id": {
                "category": "男装",
                "specification": "件"
            },
            "total": 675.0
        },
        {
            "_id": {
                "category": "女装",
                "specification": "件"
            },
            "total": 448.0
        }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    二、时间范围查询

    方式一:

        /**
         * 同一个字段 按范围查询
         * @return
         */
        @RequestMapping("/findInfoByTime")
        public List findInfoByTime(@RequestBody Product product){
            Criteria criteria = new Criteria();
            //创建时间  开始时间  结束时间
            if(!ObjectUtils.isEmpty(product.getStartTime()) || !ObjectUtils.isEmpty(product.getEndTime())){
                criteria = criteria.and("create_time");
                if(!ObjectUtils.isEmpty(product.getStartTime())){
                    criteria.gte(product.getStartTime());
                }
                if(!ObjectUtils.isEmpty(product.getEndTime())){
                    criteria.lte(product.getEndTime());
                }
            }
            //下面的写法报错:Due to limitations of the org.bson.Document, you can't add a second 'create_time' expression specified as 'create_time : Document{{$lte=Thu Jun 02 12:08:00 CST 2022}}'.
            // Criteria already contains 'create_time : Document{{$gte=Sun May 29 12:08:00 CST 2022}}'.
    //        if(!ObjectUtils.isEmpty(product.getStartTime())){
    //            criteria = criteria.and("create_time").gte(product.getStartTime());
    //        }
    //        if(!ObjectUtils.isEmpty(product.getEndTime())){
    //            criteria = criteria.and("create_time").lte(product.getEndTime());
    //        }
            Query query = Query.query(criteria);
            //排序规则 根据分类倒叙,排序升序
            query.with(Sort.by(
                    Sort.Order.desc("category"),
                    Sort.Order.asc("sort")
            ));
            List list=mongoTemplate.find(query,Product.class);
            return list;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    方式二:

        /**
         * 时间范围检索
         * @param product
         * @return
         */
        @RequestMapping("/findInfoByTime1")
        public List testTimeRange(@RequestBody Product product){
            Query query = new Query();
            ArrayList list = new ArrayList();
            if(!ObjectUtils.isEmpty(product.getStartTime())){
                list.add(Criteria.where("create_time").gte(product.getStartTime()));
            }
            if(!ObjectUtils.isEmpty(product.getEndTime())){
                list.add(Criteria.where("create_time").lte(product.getEndTime()));
            }
            Criteria[] arr = new Criteria[list.size()];
            if (arr.length > 0){
                list.toArray(arr);
                Criteria criteria = new Criteria().andOperator(arr);
                query.addCriteria(criteria);
            }
            //排序规则 根据分类倒叙,排序升序
            query.with(Sort.by(
                    Sort.Order.desc("category"),
                    Sort.Order.asc("sort")
            ));
            List productList=mongoTemplate.find(query,Product.class);
            return productList;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    三、去重排序查询

    使用mongoTemplate去重排序查询:

    第一种,使用mongoTemplate.findDistinct去重,不支持排序,即使你的query条件带sort排序方法。
    mongoTemplate.findDistinct去重,会使排序失效。
    优点:查询效率高
    缺点:只返回单一字段。不可多字段返回。不能使用排序,不推荐使用

    String id ="111";
    Query query = new Query();
    query.addCriteria(Criteria.where("_id").is(id)).with(Sort.by(Sort.Order.desc("create_time")));
    List list = mongoTemplate.find(query, Product.class);
    List activeCodes = mongoTemplate.findDistinct(query, "name",  "product",Product.class, Product.class);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    第二种,使用mongoTemplate.aggregate去重支持排序。推荐使用
    优点:可指定返回类型。支持排序
    缺点:排序是查询效率会变的非常低

    //根据 "category","create_time" 去重统计  使用mongoTemplate.aggregate去重,支持排序。推荐使用 优点:可指定返回类型。支持排序 缺点:排序是查询效率会变的非常低
    Aggregation agg = Aggregation.newAggregation(
            // 挑选所需的字段,类似select *,*所代表的字段内容
            Aggregation.project("title", "category","sale_num","create_time"),
            // sql where 语句筛选符合条件的记录
            Aggregation.match(criteria),
            // 分组条件,设置分组字段
            Aggregation.group("category","create_time")
                    //first,as里最后包含展示的字段
                    .first("title").as("title")
                    .first("category").as("category")
                    .first("sale_num").as("sale_num")
                    .first("create_time").as("create_time")
            ,
            // 排序(根据某字段排序 倒序)
            Aggregation.sort(Sort.by(
                    Sort.Order.desc("create_time")
            )),
            // 重新挑选需要字段(上面 as 后的 字段)
            Aggregation.project("title", "category","sale_num"),
            //分页
            Aggregation.skip((long) (Page > 0 ? (Page - 1) * pageSize : 0)),
            Aggregation.limit(pageSize)
    );
    AggregationResults results = mongoOperations.aggregate(agg, "product", Product.class);
    List list= results.getMappedResults();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    根据某字段去重统计(分组统计) Aggregation 分组、分页

        /**
         * 根据某字段去重统计(分组统计) Aggregation 分组、分页
         * @return
         */
        @RequestMapping("/findDistinctInfo")
        public Map  findDistinctInfo(@RequestParam("page") Integer Page,@RequestParam("pageSize") Integer pageSize){
            Map resultMap = new HashMap<>();
            //从mongodb里获取最新的一条记录
            Criteria criteria = new Criteria();
    
            //根据 "category","create_time" 去重统计  使用mongoTemplate.aggregate去重,支持排序。推荐使用 优点:可指定返回类型。支持排序 缺点:排序是查询效率会变的非常低
            Aggregation agg = Aggregation.newAggregation(
                    // 挑选所需的字段,类似select *,*所代表的字段内容
                    Aggregation.project("title", "category","sale_num","create_time"),
                    // sql where 语句筛选符合条件的记录
                    Aggregation.match(criteria),
                    // 分组条件,设置分组字段
                    Aggregation.group("category","create_time")
                            //first,as里最后包含展示的字段
                            .first("title").as("title")
                            .first("category").as("category")
                            .first("sale_num").as("sale_num")
                            .first("create_time").as("create_time")
                    ,
                    // 排序(根据某字段排序 倒序)
                    Aggregation.sort(Sort.by(
                            Sort.Order.desc("create_time")
                    )),
                    // 重新挑选需要字段(上面 as 后的 字段)
                    Aggregation.project("title", "category","sale_num"),
                    //分页
                    Aggregation.skip((long) (Page > 0 ? (Page - 1) * pageSize : 0)),
                    Aggregation.limit(pageSize)
            );
            AggregationResults results = mongoOperations.aggregate(agg, "product", Product.class);
            List list= results.getMappedResults();
            //统计去重后的 总个数
            Aggregation aggregation = Aggregation.newAggregation(Aggregation.match(criteria),
                    //按"category","create_time" 多字段分组去重统计
                    Aggregation.group("category","create_time").first("category").as("category")
            );
            AggregationResults aggregate = mongoTemplate.aggregate(aggregation, Product.class, Map.class);
    
            resultMap.put("total",aggregate.getMappedResults().size());
            resultMap.put("list",list);
            return resultMap;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    返回结果:

    {
        "total": 14,
        "list": [
            {
                "id": "{"category": "文具", "create_time": "2022-06-04 12:10:00"}",
                "title": "乐普升修正带学生用笔形涂改带实惠装",
                "price": null,
                "category": "文具",
                "specification": null,
                "saleNum": 345,
                "sort": null,
                "remark": null,
                "createTime": null,
                "updateTime": null,
                "status": null,
                "startTime": null,
                "endTime": null
            }
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    四、组合排序

    Criteria criteria = new Criteria();
    Query query = Query.query(criteria);
    //排序规则 根据分类倒叙,排序升序
    query.with(Sort.by(
            Sort.Order.desc("category"),
            Sort.Order.asc("sort")
    ));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    五、分页查询

    1.普通的分页

        /**
         * 分页获取数据列表
         * @param page 当前页数
         * @param pageSize 每页显示数量
         * @return
         */
        @RequestMapping("/findInfoByPage")
        public Map findInfoByPage(@RequestParam("page") Integer page,@RequestParam("pageSize") Integer pageSize){
            Map result = new HashMap<>();
    
            Criteria criteria = new Criteria();
            Query query = Query.query(criteria);
            //排序规则 根据分类倒叙,排序升序
            query.with(Sort.by(
                    Sort.Order.desc("category"),
                    Sort.Order.asc("sort")
            ));
            //获取总个数
            Long count = mongoTemplate.count(query,Product.class);
            //分页
            PageRequest pageRequest = PageRequest.of(page-1,pageSize);
            //分页=== 也可以用 query.skip(当前页-1).limit(页的大小)
            query.with(pageRequest);
    
            List list=mongoTemplate.find(query,Product.class);
            result.put("total",count);
            result.put("list",list);
            return result;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    2.分组分页

    //从mongodb里获取最新的一条记录
    Criteria criteria = new Criteria();
    
    //根据 "category","create_time" 去重统计  使用mongoTemplate.aggregate去重,支持排序。推荐使用 优点:可指定返回类型。支持排序 缺点:排序是查询效率会变的非常低
    Aggregation agg = Aggregation.newAggregation(
            // 挑选所需的字段,类似select *,*所代表的字段内容
            Aggregation.project("title", "category","sale_num","create_time"),
            // sql where 语句筛选符合条件的记录
            Aggregation.match(criteria),
            // 分组条件,设置分组字段
            Aggregation.group("category","create_time")
                    //first,as里最后包含展示的字段
                    .first("title").as("title")
                    .first("category").as("category")
                    .first("sale_num").as("sale_num")
                    .first("create_time").as("create_time")
            ,
            // 排序(根据某字段排序 倒序)
            Aggregation.sort(Sort.by(
                    Sort.Order.desc("create_time")
            )),
            // 重新挑选需要字段(上面 as 后的 字段)
            Aggregation.project("title", "category","sale_num"),
            //分页
            Aggregation.skip((long) (Page > 0 ? (Page - 1) * pageSize : 0)),
            Aggregation.limit(pageSize)
    );
    AggregationResults results = mongoOperations.aggregate(agg, "product", Product.class);
    List list= results.getMappedResults();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    如何理解相位噪声与时间抖动的关系?
    MMDetection 简单教程之配置文件(MMDetection3D也可从此开始学习)
    c++实现图书管理系统v1.0
    【深度学习】数学基础
    在小程序中对flex布局的理解
    一场互联网与实体经济的深度融合,正头部企业的身上上演着
    C++拿几道题练练手吧
    智能井盖监测系统功能,万宾科技传感器效果
    大学4年做出来这个算不算丢人
    Java内部类
  • 原文地址:https://blog.csdn.net/web18224617243/article/details/126114329