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

news2024/9/28 7:59:07

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

  • 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();
        // 按商家id
        String 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2104197.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分类预测|基于蜣螂优化极限梯度提升决策树的数据分类预测Matlab程序DBO-Xgboost 多特征输入单输出 含基础模型

分类预测|基于蜣螂优化极限梯度提升决策树的数据分类预测Matlab程序DBO-Xgboost 多特征输入单输出 含基础模型 文章目录 一、基本原理1. 数据准备2. XGBoost模型建立3. DBO优化XGBoost参数4. 模型训练5. 模型评估6. 结果分析与应用原理总结 二、实验结果三、核心代码四、代码获…

龙兴物联5G物联网主机:开启电力智能化新篇章

在当今时代&#xff0c;电力行业的智能化已成为不可阻挡的趋势。随着社会对电力需求的持续增长以及对供电质量和可靠性要求的不断提高&#xff0c;传统的电力系统管理模式逐渐难以满足需求。 智能化技术的融入为电力系统带来了革命性的变革。通过先进的传感器、通信网络和数据分…

ELK系列之一---探索ELK奇妙世界:初识日志界大名鼎鼎的ES集群!

目录 一、为什么要使用ELK 二、ELK简介 三、Elaticsearch入门 3.1、什么是elaticsearch 3.2、elaticsearch的底层优点 3.2.1、全文检索 3.2.2、倒排索引 3.3、elaticsearch集群原理 一、为什么要使用ELK 一般我们需要进行日志分析场景&#xff1a;直接在日志文件中 gre…

Linux -文件I/O操作

文章目录 C语言文件I/O相关函数操作fopen/fcolsefwritefseekfprintf/fscanffgets/fputs 系统调用相关接口open/closewrite/read C语言文件I/O相关函数操作 fopen/fcolse fopen 函数用于打开一个文件&#xff0c;并根据指定的模式&#xff08;如只读、只写、读写等&#xff09…

SaaS行业渠道管理的深度探索:两种增长模式哪个更强?

在当今数字化时代&#xff0c;SaaS&#xff08;Software-as-a-Service&#xff09;行业正以前所未有的速度重塑企业运营模式。随着市场的日益成熟与竞争的加剧&#xff0c;渠道管理不再仅仅是产品销售的通道&#xff0c;而是成为了SaaS企业构建生态体系、实现业务飞跃的重要策略…

分类预测|基于粒子群优化轻量级梯度提升机算法数据预测Matlab程序PSO-LightGBM 多特征输入多类别输出

分类预测|基于粒子群优化轻量级梯度提升机算法数据预测Matlab程序PSO-LightGBM 多特征输入多类别输出 文章目录 一、基本原理二、实验结果三、核心代码四、代码获取五、总结 分类预测|基于粒子群优化轻量级梯度提升机算法数据预测Matlab程序PSO-LightGBM 多特征输入多类别输出 …

电脑录屏软件哪家强?这6款高效免费工具让你轻松捕捉电脑屏幕

在数字化浪潮的推动下&#xff0c;电脑录屏软件的选择变得琳琅满目&#xff0c;本文旨在帮助您挑选出最适合您需求的录屏工具。 电脑录屏软件在我们的日常工作、学习乃至娱乐活动中扮演着越来越重要的角色。无论是为了记录PPT的演示过程、捕捉QQ、微信、腾讯会议等设计软件的对…

C8T6超绝模块--按键检测点亮LED

C8T6超绝模块–按键检测点亮LED 大纲 按键原理初始化LED初始化按键编写main 具体案例 按键原理 (这里针对的是我的板子的原理图&#xff0c;具体的查看自己的板子)注意看&#xff0c;这里按键一端接到的是地&#xff0c;当我们没按下按键时&#xff0c;其默认是低电压&…

linux环境下升级nodejs版本

文章目录 简介清除缓存信息确保已安装Node.js和npm安装n模块使用n来升级Node.js查看可用的Node.js版本升级Node.js到最新版本注意事项版本兼容性考虑 简介 在Linux环境下&#xff0c;使用npm的n模块来升级Node.js版本是一种非常流行且便捷的方法。n是一个Node.js版本管理工具&…

【OpenCV】通过迭代器获取图像的像素

文章目录 1. 前置知识2. 通过迭代器获取图像的像素 1. 前置知识 &#x1f427; 什么叫做像素&#xff1f; 最小的 图像单元&#xff0c;每个像素可以看成图像中的一个点&#xff0c;它具有颜色、亮度等属性。 cv::Mat是OpenCV中用来处理图像数据的主要数据结构&#xff0c;他实…

tomato靶场通关攻略

1.御剑2014找到IP地址 2.dirb扫描目录 3.再次详细扫描目录 4.访问找到的目录文件 进入antibots中 5.搜寻一会再info.php里面发现有东西 6.这个地方貌似可以进行利用 7.查看源代码发现包含include文件上传漏洞 8.网址后面跟?image../../../../../../../etc/passwd 9.既然可以查…

ceph-iscsi 手动安装过程中的一些问题记录以及解决办法

ceph-iscsi 手动安装教程 安装教程&#xff0c;建议直接看官方文档&#xff0c;猛戳传送门。官方教程是英文版的&#xff08;不知道有没有中文版&#xff09;&#xff0c;都是一些基础英语&#xff0c;问题不大&#xff0c;实在不行找个翻译软件帮帮忙&#xff0c;哈哈哈。 多…

黄力医生揭秘血栓‘成长’之路,七类人群需高度警惕!

血栓&#xff0c;这个潜伏在血液中的“隐形杀手”&#xff0c;悄无声息地阻塞着生命的通道。它如同道路上的障碍&#xff0c;一旦形成&#xff0c;便可能随着血液流向身体各处&#xff0c;引发脑梗、心梗甚至肺栓塞等严重后果。然而&#xff0c;大多数血栓在形成初期并无明显症…

CodeMeter赋能工业应用程序市场,实现安全与灵活的应用管理

面临挑战 在快速发展的工业自动化领域&#xff0c;软件保护和许可成为各行业决策者日常面临的关键问题。无论是自制还是购买&#xff0c;都需应对复杂的集成任务和多样化的用户需求。对于软件开发者来说&#xff0c;将先进的保护和许可技术&#xff08;如CodeMeter&#xff09;…

ISO 26262中的失效率计算:SN 29500-11 Expected values for contactors

目录 引言 1 基准条件下的失效率 2 失效率转换 2.1 失效率预测模型 2.2 开关速率应力系数 2.3 电压应力系数 2.3.1 电压应力系数计算模型 2.3.2 电压应力系数计算 2.4 电流应力系数 2.4.1 电流应力系数计算模型 2.4.2 电流应力系数计算 2.5 温度应力系数 2.6 环境…

Web前端 lucky-canvas【大转盘 九宫格 老虎机】抽奖插件(适用JS/TS、Vue、React、微信小程序、Uniapp和Taro)

Web前端 lucky-canvas 抽奖插件&#xff08;JS/TS、Vue、React、微信小程序、Uniapp和Taro&#xff09; 基于 JS Canvas 实现的【大转盘 & 九宫格 & 老虎机】抽奖&#xff0c;致力于为 WEB 前端提供一个功能强大且专业可靠的营销组件&#xff0c;只需要通过简单配置即…

一篇常见第三方库之以及详细使用示例教程

作者&#xff1a;郭震 我们介绍了几个常用的 Python 第三方库,包括 NumPy、Pandas、Matplotlib 和 Requests.本篇将通过一些简单的示例来演示如何有效地使用这些库,以帮助小白理解它们的基本用法.通过这些案例,你可以直观感受到这些库在日常编程中的价值. NumPy NumPy 是一个强…

计算机毕业设计选题推荐-动漫网站-动漫管理系统-Java/Python

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

虚拟化pve查看存储空间使用情况

通过命令行查看 pvesm 是 Proxmox VE 的存储管理工具&#xff0c;可以用来查看存储空间的使用情况。 pvesm status这个命令会列出所有配置的存储设备及其使用情况&#xff0c;包括总空间、已用空间和可用空间。 在 Proxmox VE (PVE) 中&#xff0c;local 和 local-lvm 是两种…

软考超详细准备之软件设计师的计算机系统题型一(上午题)

目录 考试技巧: 上午题: 下午题: 第一道数据流图 第二道数据库 第三道 UML 第四道算法题 第五道程序题 软考刷题之计算机系统 cpu 相关习题 运算器 相关习题 控制器 相关习题 计算机的基本单位: 加法: ​编辑 加减法 相关习题 数据表示 各种码制的范围 相…