当前位置: 首页 > news >正文

【MongoDB】多种聚合操作详解,案例分析

1. 算术表达式操作符 ($abs)

// 插入数据
db.temperatureChange.insertMany([{ _id: 1, startTemp: 50, endTemp: 80 },{ _id: 2, startTemp: 40, endTemp: 40 },{ _id: 3, startTemp: 90, endTemp: 70 },{ _id: 4, startTemp: 60, endTemp: 70 }
]);// 计算温度差的绝对值
db.temperatureChange.aggregate([{$project: {delta: { $abs: { $subtract: ["$startTemp", "$endTemp"] } }}}
]);

2. 数组表达式操作符 ($arrayElemAt)

// 插入数据
db.users.insertMany([{ _id: 1, name: "dave123", favorites: ["chocolate", "cake", "butter", "apples"] },{ _id: 2, name: "li", favorites: ["apples", "pudding", "pie"] },{ _id: 3, name: "ahn", favorites: ["pears", "pecans", "chocolate", "cherries"] },{ _id: 4, name: "ty", favorites: ["ice cream"] }
]);// 获取数组首尾元素
db.users.aggregate([{$project: {name: 1,first: { $arrayElemAt: ["$favorites", 0] },last: { $arrayElemAt: ["$favorites", -1] }}}
]);

3. 按位操作符 ($bitAnd)

// 插入数据
db.switches.insertMany([{ _id: 0, a: NumberInt(0), b: NumberInt(127) },{ _id: 1, a: NumberInt(2), b: NumberInt(3) },{ _id: 2, a: NumberInt(3), b: NumberInt(5) }
]);// 按位与运算
db.switches.aggregate([{$project: {result: { $bitAnd: ["$a", "$b"] }}}
]);

4. 布尔表达式操作符 ($and)

// 插入数据
db.inventory.insertMany([{ _id: 1, item: "abc1", qty: 300 },{ _id: 2, item: "abc2", qty: 200 },{ _id: 3, item: "xyz1", qty: 250 },{ _id: 4, item: "wxz1", qty: 300 },{ _id: 5, item: "wxz2", qty: 180 }
]);// 检查数量范围
db.inventory.aggregate([{$project: {item: 1,qty: 1,result: { $and: [{ $gt: ["$qty", 100] },{ $lt: ["$qty", 250] }]}}}
]);

5. 条件表达式操作符 ($cond)

// 插入数据
db.inventory.insertMany([{ _id: 1, item: "abc1", qty: 300 },{ _id: 2, item: "abc2", qty: 200 },{ _id: 3, item: "xyz1", qty: 260 }
]);// 条件折扣计算
db.inventory.aggregate([{$project: {item: 1,discount: {$cond: {if: { $gte: ["$qty", 260] },then: 30,else: 20}}}}
]);

6. 日期操作符 ($dateAdd)

// 插入数据
db.shipping.insertMany([{ custId: 456, purchaseDate: ISODate("2020-12-31") },{ custId: 457, purchaseDate: ISODate("2021-02-28") },{ custId: 458, purchaseDate: ISODate("2021-02-26") }
]);// 计算预计交付日期(+3天)
db.shipping.aggregate([{$project: {expectedDeliveryDate: {$dateAdd: {startDate: "$purchaseDate",unit: "day",amount: 3}}}}
]);

7. 字符串操作符 ($concat)

// 插入数据
db.inventory.insertMany([{ _id: 1, item: "ABC1", description: "product 1" },{ _id: 2, item: "ABC2", description: "product 2" },{ _id: 3, item: "XYZ1", description: null }
]);// 拼接字符串
db.inventory.aggregate([{$project: {itemDescription: { $concat: ["$item", " - ", "$description"] }}}
]);

8. 累加器操作符 ($addToSet)

// 插入数据
db.sales.insertMany([{ _id: 1, item: "abc", date: ISODate("2014-01-01T08:00:00Z") },{ _id: 2, item: "jkl", date: ISODate("2014-02-03T09:00:00Z") },{ _id: 3, item: "xyz", date: ISODate("2014-02-03T09:05:00Z") },{ _id: 4, item: "abc", date: ISODate("2014-02-15T08:00:00Z") }
]);// 按日期分组统计唯一商品
db.sales.aggregate([{$group: {_id: {day: { $dayOfYear: "$date" },year: { $year: "$date" }},itemsSold: { $addToSet: "$item" }}}
]);

9. 变量操作符 ($let)

// 插入数据
db.sales.insertMany([{ _id: 1, price: 10, tax: 0.50, applyDiscount: true },{ _id: 2, price: 10, tax: 0.25, applyDiscount: false }
]);// 使用变量计算最终价格
db.sales.aggregate([{$project: {finalTotal: {$let: {vars: {total: { $add: ["$price", "$tax"] },discounted: { $cond: { if: "$applyDiscount", then: 0.9, else: 1 } }},in: { $multiply: ["$$total", "$$discounted"] }}}}}
]);

关键说明:

  1. 字段修正:所有 -id 已修正为 _id
  2. 数据类型
    • 日期使用 ISODate()
    • 整数使用 NumberInt()
  3. 操作符注意
    • $arrayElemAt:索引从0开始,-1表示最后一个元素
    • $cond:三元运算符(条件 ? 值1 : 值2)
    • $let:先定义变量再使用($$变量名
  4. 执行顺序
    1. 创建集合 → 2. 插入数据 → 3. 执行聚合管道
    
  5. 版本要求
    • 按位操作符需要 MongoDB 6.3+
    • 窗口函数需要 MongoDB 5.0+

建议逐段复制执行,每次执行前确保集合存在且数据格式正确。遇到语法错误时,检查括号闭合和逗号使用。


$mergeObjects 与集合表达式

场景说明

我们有两个集合:orders(订单)和items(商品)。我们需要将这两个集合的数据按照商品编号(item)进行关联,得到包含订单信息和商品库存信息的完整文档。

准备数据
// 创建orders集合并插入数据
db.orders.insertMany([{ "_id": 1, "item": "abc", "price": 12, "ordered": 2 },{ "_id": 2, "item": "jkl", "price": 20, "ordered": 1 }
])
// 创建items集合并插入数据
db.items.insertMany([{ "_id": 1, "item": "abc", description: "product 1", "instock": 120 },{ "_id": 2, "item": "def", description: "product 2", "instock": 80 },{ "_id": 3, "item": "jkl", description: "product 3", "instock": 60 }
])
执行$lookup聚合操作

我们分三次执行,以便更好理解命令参数

  • 左连接操作(orders)
db.orders.aggregate([{$lookup: {from: "items",localField: "item", // ordersforeignField: "item",	// itemsas: "fromItems"}}
])
  • 可以看到orders的左连接合并结果是以我们提供的 as: "fromItems"为字段的数组
    在这里插入图片描述
  • 我们需要把数组提出来,合并到根文档上,让两表各自所需的字段合在一起
db.orders.aggregate([{$lookup: {from: "items",localField: "item",foreignField: "item",as: "fromItems"}},{$replaceRoot: {newRoot: {$mergeObjects: [{ $arrayElemAt: ["$fromItems", 0]},"$$ROOT"]}}}
])

在这里插入图片描述

  • 接下来就是隐藏fromItems数组
db.orders.aggregate([{$lookup: {from: "items",localField: "item",foreignField: "item",as: "fromItems"}},{$replaceRoot: {newRoot: {$mergeObjects: [{ $arrayElemAt: ["$fromItems", 0]},"$$ROOT"]}}},{$project: { fromItems: 0}}
])

在这里插入图片描述


http://www.lryc.cn/news/625186.html

相关文章:

  • 启发式合并
  • powershell中的cmdlet
  • 【每日一题】Day 7
  • MySQL架构和储存引擎
  • Web安全 - 构建安全可靠的API:基于国密SM2/SM3的文件上传方案深度解析
  • 多智能体架构设计:从单Agent到复杂系统的演进逻辑
  • 人工智能 | 基于大数据的皮肤病症状数据可视化分析系统(matlab源码)
  • 发布npmjs组件库
  • AopAutoConfiguration源码阅读
  • 鼠标右键没有“通过VSCode打开文件夹”
  • JVM学习笔记-----类加载
  • FPGA-Vivado2017.4-建立AXI4用于单片机与FPGA之间数据互通
  • Google 的 Opal:重新定义自动化的 AI 平台
  • WPF 打印报告图片大小的自适应(含完整示例与详解)
  • Rust 入门 生命周期-next2 (十九)
  • 牛津大学xDeepMind 自然语言处理(1)
  • Centos7 使用lamp架构部署wordpress
  • 接口和抽象类的区别(面试回答)
  • 【深度长文】Anthropic发布Prompt Engineering全新指南
  • Java面向对象三大特性:封装、继承、多态深度解析与实践应用
  • ⭐CVPR2025 RigGS:从 2D 视频到可编辑 3D 关节物体的建模新范式
  • 音频分类模型笔记
  • OOP三大特性
  • 【计算机视觉与深度学习实战】05计算机视觉与深度学习在蚊子检测中的应用综述与假设
  • 网络基础——协议认识
  • Pytest项目_day18(读取ini文件)
  • Unity 中控开发 多路串口服务器(一)
  • 深层语义知识图谱:提升NLP文本预处理效果的关键技术
  • C++ 多进程编程深度解析【C++进阶每日一学】
  • 一个基于纯前端技术实现的五子棋游戏,无需后端服务,直接在浏览器中运行。