MongoDB聚合查询解析:多维数据关联和聚合

什么是聚合查询

在真实的业务环境,我们的表/文档肯定不止一个,常常需要在多个表之间进行关联查询。那么在MongoDB 中如何做多张表的关联查询了,这就需要用到聚合查询。

MongoDB中聚合(aggregate) 操作将来自多个document的value组合在一起,并通过对分组数据进行各种操作处理,并返回计算后的数据结果,主要用于处理数据(诸如统计平均值,求和等)。有点类似sql语句中的 count(*)、group by,但聚合查询功能要更加强大。

有哪些聚合查询的方法

MongoDB提供了三种方式去执行聚合操作:

  • Pipeline 聚合管道
  • 单一目的聚合方法
  • Map-Reduce

不过从从MongoDB 5.0 开始,map-reduce 已被弃用。

聚合管道

聚合管道是由aggregation framework将文档进入一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的聚合结果。

如图所示:

上图的操作,代码如下:

php 复制代码
db.orders.aggregate([
  { $match: { status: "A" } },
  { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }
])
  • $match阶段:通过status字段过滤出符合条件的Document(即是Status等于"A"的Document);
  • $group 阶段:按cust_id字段对Document进行分组,以计算每个唯一cust_id的金额总和。

相当于 SQL 中的以下语句:

vbnet 复制代码
select cust_id as _id, sum(amount) as total from orders where status like "%A%" group by cust_id;

管道操作符

MongoDB管道 功能描述 SQL操作/函数
$match 文档过滤器 where
$group 分组统计器 group by
$project 字段整形师:修改输入文档的结构(例如重命名,增加、删除字段等) select
$sort 对结果排序 order by
$limit 限制管道输出的结果个数 limit
$skip 跳过制定数量的结果,并且返回剩下的结果
处理数组类型字段
$lookup 实现类似JOIN操作 join
$addFields 新增计算字段
$bucket 数据分布分析

想象你在玩俄罗斯套娃:

  1. $match:先筛掉不想要的娃娃(文档过滤)
  2. $unwind:拆开大礼包(数组展开)
  3. $group:按颜色分类(分组统计)
  4. $project:给娃娃穿新衣服(字段重塑)

字段路径

字段路径 是访问文档中字段的特殊语法,使用 $ 前缀标识字段层级关系,支持访问嵌套结构和数组元素。

核心语法规则:

  1. 根字段$字段名
    例:$name 访问顶层name字段
  2. 嵌套字段$父字段.子字段
    例:$address.city 访问address对象中的city
  3. 数组元素
    $数组字段.子字段 → 访问数组内元素的子字段
    $数组字段[index] → 访问指定索引元素

文档结构:

css 复制代码
// orders集合文档示例
{
_id: 1,
order_no: "ORD202301",
items: [
    { product: "手机", price: 2999, qty: 2 },
    { product: "耳机", price: 399, qty: 1 }
  ],
customer: {
    name: "张三",
    vip_level: 3
  }
}

聚合管道应用:

php 复制代码
db.orders.aggregate([
  { $unwind: "$items" }, // 展开订单商品数组
  { $project: {
      order_id: "$order_no", // 重命名字段
      product_name: "$items.product", // 访问嵌套数组元素
      total_price: { 
        $multiply: ["$items.price", "$items.qty"] // 计算字段
      },
      is_vip: { 
        $cond: { if: { $gte: ["$customer.vip_level", 3] }, then: "是", else: "否" } // 条件判断
      }
  }},
  { $match: { 
    total_price: { $gt: 1000 }, // 过滤高价商品
    is_vip: "是"
  }}
])

输出结果:

css 复制代码
[  {    "_id": 1,    "order_id": "ORD202301",    "product_name": "手机",    "total_price": 5998,    "is_vip": "是"  }]

注意事项

  1. 严格区分大小写$Customer$customer
  2. 空值处理 :访问不存在的字段返回null
  3. 特殊字符 :字段名含.时需用$["field.name"]语法
  4. 性能影响:频繁访问深层嵌套字段可能影响查询速度

通过合理使用字段路径,可以像操作对象属性一样灵活处理文档数据,是构建高效聚合管道的基石!

单一目的聚合方法

单一目的聚合方法聚合单个集合中的文档。这些方法很简单,但缺乏聚合管道的功能。

方法 说明
db.collection.estimatedDocumentCount() 返回集合或视图中文档的近似数量
db.collection.count() 返回集合或视图中文档的数量
db.collection.distinct() 返回具有指定字段的不同值的文档数组

总结

聚合查询就像给你的MongoDB装上涡轮增压引擎,当你能熟练驾驭这个工具时,海量数据将不再是令人头疼的负担,而是等待挖掘的金矿。记住:优秀的开发者用find,卓越的数据工程师用aggregate

相关推荐
_星辰大海乀5 分钟前
表的设计、聚合函数
java·数据结构·数据库·sql·mysql·数据库开发
未来之窗软件服务1 小时前
solidwors插件 开发————仙盟创梦IDE
前端·javascript·数据库·ide·仙盟创梦ide
yc_12241 小时前
SqlHelper 实现类,支持多数据库,提供异步操作、自动重试、事务、存储过程、分页、缓存等功能。
数据库·c#
Leo.yuan2 小时前
基于地图的数据可视化:解锁地理数据的真正价值
大数据·数据库·信息可视化·数据挖掘·数据分析
好吃的肘子2 小时前
MongoDB入门
数据库·mongodb
noravinsc2 小时前
人大金仓数据库 与django结合
数据库·python·django
代码配咖啡3 小时前
《Navicat之外的新选择:实测支持国产数据库的SQLynx核心功能解析》
数据库
懒大王爱吃狼3 小时前
怎么使用python进行PostgreSQL 数据库连接?
数据库·python·postgresql
时序数据说3 小时前
IoTDB集群的一键启停功能详解
大数据·数据库·开源·时序数据库·iotdb
小叶子来了啊4 小时前
信息系统运行管理员:临阵磨枪版
运维·服务器·数据库