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

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

目录

一、分组统计(Aggregation)

1.按某字段分组统计

    /**
     * 根据分类名称 分组统计销售数量
     * @param dataType 1:本日 2:本月 3:本年
     * @return
     */
    @RequestMapping("/findInfoByGroup")
    public List<Map> 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<Map> aggregationResults = mongoTemplate.aggregate(aggregation,Product.class,Map.class);
        List<Map> list = aggregationResults.getMappedResults();

        return list;
    }

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

返回结果:

[
    {
        "_id": "口红",
        "total": 2224.0
    },
    {
        "_id": "面膜",
        "total": 997.0
    },
    {
        "_id": "文具",
        "total": 799.0
    },
    {
        "_id": "男装",
        "total": 675.0
    },
    {
        "_id": "女装",
        "total": 448.0
    }
]

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

2.多字段分组统计

    /**
     * 根据分类名称和规格 分组统计销售数量
     * @param
     * @return
     */
    @RequestMapping("/findInfoByGroup1")
    public List<Map> 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<Map> aggregationResults = mongoTemplate.aggregate(aggregation,Product.class,Map.class);
        List<Map> list = aggregationResults.getMappedResults();

        return list;
    }

返回结果:

[
    {
        "_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
    }
]

二、时间范围查询

方式一:

    /**
     * 同一个字段 按范围查询
     * @return
     */
    @RequestMapping("/findInfoByTime")
    public List<Product> 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<Product> list=mongoTemplate.find(query,Product.class);
        return list;
    }

方式二:

    /**
     * 时间范围检索
     * @param product
     * @return
     */
    @RequestMapping("/findInfoByTime1")
    public List<Product> testTimeRange(@RequestBody Product product){
        Query query = new Query();
        ArrayList<Criteria> list = new ArrayList<Criteria>();
        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<Product> productList=mongoTemplate.find(query,Product.class);
        return productList;
    }

三、去重排序查询

使用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<Product> list = mongoTemplate.find(query, Product.class);
List<Product> activeCodes = mongoTemplate.findDistinct(query, "name",  "product",Product.class, Product.class);

第二种,使用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<Product> results = mongoOperations.aggregate(agg, "product", Product.class);
List<Product> list= results.getMappedResults();

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

    /**
     * 根据某字段去重统计(分组统计) Aggregation 分组、分页
     * @return
     */
    @RequestMapping("/findDistinctInfo")
    public Map<String,Object>  findDistinctInfo(@RequestParam("page") Integer Page,@RequestParam("pageSize") Integer pageSize){
        Map<String,Object> 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<Product> results = mongoOperations.aggregate(agg, "product", Product.class);
        List<Product> list= results.getMappedResults();
        //统计去重后的 总个数
        Aggregation aggregation = Aggregation.newAggregation(Aggregation.match(criteria),
                //按"category","create_time" 多字段分组去重统计
                Aggregation.group("category","create_time").first("category").as("category")
        );
        AggregationResults<Map> aggregate = mongoTemplate.aggregate(aggregation, Product.class, Map.class);

        resultMap.put("total",aggregate.getMappedResults().size());
        resultMap.put("list",list);
        return resultMap;
    }

返回结果:

{
    "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
        }
    ]
}

四、组合排序

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

五、分页查询

1.普通的分页

    /**
     * 分页获取数据列表
     * @param page 当前页数
     * @param pageSize 每页显示数量
     * @return
     */
    @RequestMapping("/findInfoByPage")
    public Map<String,Object> findInfoByPage(@RequestParam("page") Integer page,@RequestParam("pageSize") Integer pageSize){
        Map<String,Object> 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<Product> list=mongoTemplate.find(query,Product.class);
        result.put("total",count);
        result.put("list",list);
        return result;
    }

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<Product> results = mongoOperations.aggregate(agg, "product", Product.class);
List<Product> list= results.getMappedResults();

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

猜你喜欢

转载自blog.csdn.net/web18224617243/article/details/126114329