MongoDB聚合管道
- 使用聚合管道可以对集合中的文档进行变换和组合
db.COLLECTION_NAME.aggregate([{<stage>}, ...])
方法构建和使用聚合管道
- 可用作 表关联查询、数据的统计
管道操作符
$project
增加、删除、重命名字段$match
条件匹配。只满足条件的文档才能进入下一阶段$limit
限制结果的数量$skip
跳过文档的数量$sort
条件排序$group
条件组合结果$lookup
引入其他集合的数据(表关联查询)
SQL和NOSQL对比
where $metch
group by $group
having $match
select $project
order by $sort
limit $limit
sum() $sum
count() $sum
join $lookup
管道表达式
- 管道操作符为 “键” 所对应的 “值” 叫做管道表达式
- 如:
{$match: {status: "A"}}
- $match 称为管道操作符
- status: “A” 称为管道表达式,是管道操作符的操作数
- 如:
- 每个管道表达式是一个文档结构,由字段名、字段值和一些表达式操作符组成的
模拟数据
db.order.insert({"order_id":"1", "uid":10, "trade_no":"111", "all_price":100, "all_num":2})
db.order.insert({"order_id":"2", "uid":7, "trade_no":"222", "all_price":90, "all_num":2})
db.order.insert({"order_id":"3", "uid":9, "trade_no":"333", "all_price":20, "all_num":6})
db.order_item.insert({"order_id":"1", "title":"鼠标", "price":50, "num":1})
db.order_item.insert({"order_id":"1", "title":"键盘", "price":50, "num":1})
db.order_item.insert({"order_id":"2", "title":"牛奶", "price":50, "num":1})
db.order_item.insert({"order_id":"2", "title":"酸奶", "price":40, "num":1})
db.order_item.insert({"order_id":"3", "title":"矿泉水", "price":2, "num":5})
db.order_item.insert({"order_id":"3", "title":"毛巾", "price":10, "num":1})
管道操作符使用
$project 修改文档的结构,可用来重命名、增加或删除文档中的字段
- 要求查找 order 表中只返回文档中的 trade_no 和 all_price 字段
db.order.aggregate([{$project:{trade_no:1, all_price: 1}}])
$match 用于过滤文档 类似于 find() 方法中的参数
-
db.order.aggregate( [ { $project: {trade_no:1, all_price: 1} }, { $match: {"all_price": {$gte: 90}} } ])
$group 将集合中的文档进行分组,可用于统计结果
-
统计每个订单的订单数量,按照订单号分组
db.order_item.aggregate( [ { $group: {_id: "$order_id", total: {$sum: "$num"}} } ] )
-
统计每个订单的总价格,按照订单号分组
db.order_item.aggregate( [ { $group: {_id: "$order_id", total: {$sum: "$price"}} } ] )
$sort 将集合中的文档进行排序
-
排序
db.order.aggregate( [ { $project: {trade_no:1, all_price: 1} }, { $match: {"all_price": {$gte: 90}} }, { $sort: {"all_price": -1} } ])
$limit
-
限制查找数量
db.order.aggregate( [ { $project: {trade_no:1, all_price: 1} }, { $match: {"all_price": {$gte: 90}} }, { $sort: {"all_price": -1} }, { $limit: 1 } ])
$skip
-
跳过查找
db.order.aggregate( [ { $project: {trade_no:1, all_price: 1} }, { $match: {"all_price": {$gte: 90}} }, { $sort: {"all_price": -1} }, { $skip: 1 } ])
$lookup
-
表关联查询
db.order.aggregate( [ { $lookup: { from: "order_item", //主表 localField: "order_id", //附属表 foreignField: "order_id", as: "items" } } ] )
-
关联后找出价格大于等于90的数据
db.order.aggregate( [ { $lookup: { from: "order_item", //主表 localField: "order_id", //附属表 foreignField: "order_id", as: "items" } }, { $match: { "all_price": {$gte: 90} } } ] )
-
边关联后添加管道过滤 并 格式化输出
db.order.aggregate(
[
{
$lookup: {
from: "order_item",
//主表
localField: "order_id",
//附属表
foreignField: "order_id",
as: "items"
}
},
{
$project: {
order_id: 1,
trade_no: 1,
all_price: 1,
items: 1
}
},
{
$match: {
"all_price": {$gte: 90}
}
},
{
$sort: {
"all_price": -1
}
}
]
).pretty()