mongodb在Java中条件分组聚合查询并且分页(时间戳,按日期分组,年月日...)

本文主要是介绍mongodb在Java中条件分组聚合查询并且分页(时间戳,按日期分组,年月日...),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

废话不多说,先看效果图:

  • SQL查询结果示例:
    在这里插入图片描述
  • 多种查询结果示例:
    在这里插入图片描述

原SQL:

db.getCollection("hbdd_order").aggregate([{// 把时间戳格式化$addFields: {orderDate: {"$dateToString": {"format": "%Y-%m-%d","date": {"$toDate": "$hzdd_order_addtime"}}}}},{$match: {// 筛选条件hzdd_order_addtime: {$gte: 1722441600000,$lt: 1725120000000}}},{// 按格式过的时间分组$group: {"_id": "$orderDate",paidAmount: {$sum: { // 统计$cond: [{ // 条件类似if true =1 else =0$eq: ["$hzdd_order_ispay", 1]}, "$hzdd_order_amount", 0]}},paidCount: {$sum: {$cond: [{$eq: ["$hzdd_order_ispay", 1]}, 1, 0]}},unpaidAmount: {$sum: {$cond: [{$eq: ["$hzdd_order_ispay", 0]}, "$hzdd_order_amount", 0]}},unpaidCount: {$sum: {$cond: [{$eq: ["$hzdd_order_ispay", 0]}, 1, 0]}}}},{$project: {date: "$_id",paidAmount: 1,paidCount: 1,unpaidAmount: 1,unpaidCount: 1}},{$sort: { // 排序date: 1}}
]);

Java语句:

代码中多了些内容,但是和SQL语句大差不差
(懒得替换类名,大家看到陌生的类就是自己建的)

import com.mongodb.client.result.UpdateResult;
import jodd.util.StringUtil;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;public Page<OrderStatVo> orderStatistical(OrderStatQuery query) { Pageable pageable = PageRequest.of(query.getPageNum() - 1, query.getPageSize());MongoTemplate mongoTemplate = mongoFactory.mongoTemplate(OrderConstants.ORDER_DB);// 时间筛选Long startTime = query.getStartTime();Long endTime = query.getEndTime();// 区分 1年,2月,3日int type = query.getType();// 按商家idString shopId = query.getShopId();// 按code筛选Integer areaCode = query.getAreaCode();Integer provinceCode = query.getProvinceCode();Integer cityCode = query.getCityCode();Integer countyCode = query.getCountyCode();// 基础匹配条件:按年初和年末 时间戳Criteria baseCriteria = new Criteria();// 额外的筛选条件List<Criteria> additionalCriteria = new ArrayList<>();if (startTime != null && endTime != null) {additionalCriteria.add(Criteria.where("hzdd_order_addtime").gte(startTime).lt(endTime));}if (StringUtil.isNotEmpty(shopId)) {additionalCriteria.add(Criteria.where("hzdd_order_sjid").is(shopId));}if (areaCode != null && areaCode != 0) {additionalCriteria.add(Criteria.where("hzdd_order_area_code").is(areaCode));}if (provinceCode != null && provinceCode != 0) {additionalCriteria.add(Criteria.where("hzdd_order_province_code").is(provinceCode));}if (cityCode != null && cityCode != 0) {additionalCriteria.add(Criteria.where("hzdd_order_city_code").is(cityCode));}if (countyCode != null && countyCode != 0) {additionalCriteria.add(Criteria.where("hzdd_order_county_code").is(countyCode));}// 合并所有条件if (!additionalCriteria.isEmpty()) {baseCriteria.andOperator(additionalCriteria.toArray(new Criteria[0]));}// 构建匹配操作MatchOperation matchOperation = Aggregation.match(baseCriteria);// 添加字段操作,将 Unix 时间戳转换为日期字符串String expression = switch (type) {case 1 -> "{$dateToString: { format: '%Y', date: { $toDate: '$hzdd_order_addtime' }}}";case 2 -> "{$dateToString: { format: '%Y-%m', date: { $toDate: '$hzdd_order_addtime' }}}";case 3 -> "{$dateToString: { format: '%Y-%m-%d', date: { $toDate: '$hzdd_order_addtime' }}}";default -> "{$dateToString: { format: '%Y-%m-%d', date: { $toDate: '$hzdd_order_addtime' }}}";};AddFieldsOperation addFieldsOperation = Aggregation.addFields().addField("orderDate").withValueOfExpression(expression).build();// 分组操作GroupOperation groupOperation = Aggregation.group("orderDate").sum(ConditionalOperators.Cond.when(Criteria.where("hzdd_order_ispay").is(1)).then("$hzdd_order_amount").otherwise(0)).as("paidAmount").sum(ConditionalOperators.Cond.when(Criteria.where("hzdd_order_ispay").is(1)).then(1).otherwise(0)).as("paidCount").sum(ConditionalOperators.Cond.when(Criteria.where("hzdd_order_ispay").is(0)).then("$hzdd_order_amount").otherwise(0)).as("unpaidAmount").sum(ConditionalOperators.Cond.when(Criteria.where("hzdd_order_ispay").is(0)).then(1).otherwise(0)).as("unpaidCount");// 投影操作ProjectionOperation projectionOperation = Aggregation.project().and("_id").as("date").andInclude("paidAmount", "paidCount", "unpaidAmount", "unpaidCount");// 排序操作SortOperation sortOperation = Aggregation.sort(Sort.Direction.ASC, "date");// 分页操作SkipOperation skipOperation = Aggregation.skip((long) pageable.getPageNumber() * pageable.getPageSize());LimitOperation limitOperation = Aggregation.limit(pageable.getPageSize());// 构建不包含分页的聚合查询以获取总条数Aggregation countAggregation = Aggregation.newAggregation(matchOperation,addFieldsOperation,groupOperation,Aggregation.group("orderDate").count().as("totalCount"), // 添加计数操作Aggregation.project("totalCount").andExclude("_id") // 只包含 totalCount 字段);// 执行聚合查询以获取总条数AggregationResults<Document> totalCountResults = mongoTemplate.aggregate(countAggregation, "hbdd_order", Document.class);Document document = totalCountResults.getMappedResults().stream().findFirst().orElse(null);int total = document != null ? (int) document.get("totalCount") : 0;// 构建包含分页的聚合查询Aggregation aggregation = Aggregation.newAggregation(matchOperation,addFieldsOperation,groupOperation,projectionOperation,sortOperation,skipOperation,limitOperation);// 第二个参数是文档名(表名),第三个参数是接收的类,字段对应上面代码中的as别名字段AggregationResults<OrderStatVo> results = mongoTemplate.aggregate(aggregation, "hbdd_order", OrderStatVo.class);List<OrderStatVo> everyDayOrderStats = results.getMappedResults();// 分页操作return new PageImpl<>(everyDayOrderStats, pageable, total);}

** OrderStatQuery 类就不展示了,就是传值进来的筛选条件 **

OrderStatVo类
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;@Data
@Schema(description = "订单统计")
public class OrderStatVo {@Schema(description = "周期")private String date;@Schema(description = "已支付金额")private Double paidAmount;@Schema(description = "已支付订单数")private Long paidCount;@Schema(description = "未支付金额")private Double unpaidAmount;@Schema(description = "未支付订单数")private Long unpaidCount;}
Java中使用mongoDB小技巧:

配置文件中加上下面这行,可以打印出mongo的SQL语句

logging:level:org.springframework.data.mongodb.core.MongoTemplate: DEBUG

这篇关于mongodb在Java中条件分组聚合查询并且分页(时间戳,按日期分组,年月日...)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1136555

相关文章

Java Stream流与使用操作指南

《JavaStream流与使用操作指南》Stream不是数据结构,而是一种高级的数据处理工具,允许你以声明式的方式处理数据集合,类似于SQL语句操作数据库,本文给大家介绍JavaStream流与使用... 目录一、什么是stream流二、创建stream流1.单列集合创建stream流2.双列集合创建str

springboot集成easypoi导出word换行处理过程

《springboot集成easypoi导出word换行处理过程》SpringBoot集成Easypoi导出Word时,换行符n失效显示为空格,解决方法包括生成段落或替换模板中n为回车,同时需确... 目录项目场景问题描述解决方案第一种:生成段落的方式第二种:替换模板的情况,换行符替换成回车总结项目场景s

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

SpringBoot中@Value注入静态变量方式

《SpringBoot中@Value注入静态变量方式》SpringBoot中静态变量无法直接用@Value注入,需通过setter方法,@Value(${})从属性文件获取值,@Value(#{})用... 目录项目场景解决方案注解说明1、@Value("${}")使用示例2、@Value("#{}"php

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——