MongoDB聚合查询
MongoDB聚合查询
·
一. MongoDB聚合框架
MongoDB聚合框架(Aggregation Framewrok)用于对集合中的数据进行一系列的运算,并将这些数据转化为所期望的形式来展示。
1. 聚合框架的作用
聚合框架 == SQL中的 GROUP BY、LEFT OUTER JOIN、AS 等
2. 聚合运算的使用场景
- OLTP:计算
- OLAP:统计、分析、汇总
3. 聚合运算的过程
- 管道(Pipeline):整个聚合运算过程
- 步骤(Stage):管道由多个步骤组成。
- 聚合运算过程:管道接收文档(原始数据),在每个步骤中对这些文档进行一系列的运算,并将结果文档输出给下一个步骤。
4. 聚合运算的基本格式
pipeline = [$stage1, $stage2, ... $stageN]; db.<COLLECTION>.aggregate( pipline, { options } );
5. 常用步骤
步骤 | 作用 | SQL等价运算符 |
---|---|---|
$match | 过滤 | WHERE |
$project | 投影:选择需要的或排除不需要的字段 | AS |
$sort | 排序 | ORDER BY |
$group | 分组 | GROUP BY |
$skip | 结果限制:跳过多少条记录 | SKIP |
$limit | 结果限制:只返回多少条记录 | LIMIT |
$lookup | 左外连接 | LEFT OUTER JOIN |
$unwind | 展开数组 | 无 |
$graphLookup | 图搜索 | 无 |
$bucket | 分面搜索:把记录进行分组 | 无 |
$facet | 分面搜索:把几个$bucket运算放在一个$facet中完成,一次性展示几种分组结果 | 无 |
6. 步骤中常用的运算符
步骤 | $match | $project | $group |
运算符 | $eq/$gt/$gte/$lt/$lte ...... | $map/$reduce/$filter ...... | $sum/$avg ...... |
7. 代码示例
注意:字段名前带$说明是集合中已有字段,字段名前不带$说明是要新增加的字段。
# $match、$skip、$limit、$project
# 从users集合中查找所有男性,跳过100个,只查出20个,只返回'名'和'姓'
db.users.aggregate([
{ $match: { gender: '男' } },
{ $skip: 100 },
{ $limit: 20 },
{ $project:
{
'名': '$first_name',
'姓': '$last_name'
}
}
]);
# $group
# 从users集合中查找所有女性,按department分组并计算员工数量,只看小于10个人的department
# emp_qty: { $sum: 1 } 员工数量计算方法:每当看到一条数据,就$sum:1,所以看到多少员工文档就加了多少次,结果就是该部门的员工总量
# emp_qty: { $lt: 10 } 员工数量要小于10
db.users.aggregate([
{ $match: { 'gender' : '女' }},
{ $group: {
_id: '$department'
emp_qty: { $sum: 1 }
}},
{ $match: { emp_qty: { $lt: 10 }}}
])
# $unwind
# students集合中数据格式
#{
# name: '张三',
# score: [
# { subject: '语文', score: 84 },
# { subject: '数学', score: 90 },
# { subject: '外语', score: 69 }
# ]
#}
# 使用$unwind将数组score展开
db.students.aggregate([$unwind: '$score'}])
# 展开后的结果
#{ name: '张三', score: {subject: '语文', score: 84 }}
#{ name: '张三', score: {subject: '数学', score: 90 }}
#{ name: '张三', score: {subject: '外语', score: 69 }}
# $bucket
# 使用$bucket把记录进行分组
# 使用$bucket按price的区间 [0,10),[10,20),[20,30),[30,40),其他 进行分组
# output: { 'count': { $sum: 1 }} 计算每个区间中有多少条记录并返回
db.products.aggregate([{
$bucket: {
groupBy: '$price',
boundaries: [0, 10, 20, 30, 40],
default: 'Other',
output: { 'count': { $sum: 1 }}
}
}])
# ¥facet 一次性展示几种分组结果
db.products.aggregate([{
$facet: {
price: {
$bucket: {...}
},
year: {
$bucket: {...}
}
}
}])
二. MongoDB聚合查询实例
1. 计算所有订单的总销售额
# _id: null表示没有分组,将所有表作为一个大分组
# 指定一个新字段total,其内容是把所有记录的$total字段值加起来
db.orders.aggregate([{
$group:{
_id: null,
total: { $sum: "$total"}
}
}])
# 结果 { "_id" : null, "total" : NumberDecimal("44019609") }
2. 查询2019年1月1日-3月31日已完成的订单总金额和订单总数
# MongoDB中要使用ISODate将数据转化为合适的日期格式
db.orders.aggregate([
// 1. 匹配条件(一般都要先做匹配)
{ $match: {
status: "completed",
orderDate: {
$gte: ISODate('2019-01-01'),
$lt: ISODate('2019-04-01')
}
}},
// 2. 聚合订单总金额、总运费、总数量
{ $group: {
_id: null,
total: { $sum: "$total" },
shippingFee: { $sum: "$shippingFee" },
count: { $sum: 1 },
}},
// 3. 投影时增加新字段grandTotal来计算$total与$shippingFee相加的总金额
{ $project: {
grandTotal: { $add: ["$total", "$shippingFee"] },
count: 1,
_id: 0
}}
])
# 结果 { "count" : 5875, "grandTotal" : NumberDecimal("2636376.00") }
三. 使用Compass把MQL转成Node.js语句
参考文章:
更多推荐
已为社区贡献7条内容
所有评论(0)