一、 MongoDB 聚合管道
用途:表关联查询、数据统计。
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
二、 MongoDB Aggregation 管道操作符与表达式
管道操作符 | SQL 和 NOSQL 对比 | Description |
---|---|---|
$project | SELECT | 修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。 |
$match | WHERE/HAVING | 条件匹配。 只满足条件的文档才能进入下 一阶段 |
$limit | LIMIT | 限制结果的数量 |
$skip | 跳过文档的数量 | |
$sort | ORDER BY | 条件排序。 |
$group | GROUP BY | 条件组合结果 统计 |
$lookup | join | $lookup 操作符 据 (表关联查询 |
管道表达式:
管道操作符作为“键”,所对应的“值”叫做管道表达式。
例如{$match:{status:"A"}}
, $match
称为管道操作符, 而 status:"A"称为管道表达式,是管道操作符的操作数(Operand)。
每个管道表达式是一个文档结构, 它是由字段名、 字段值、 和一些表达式操作符组成的。
表达式 | 描述 | 实例 |
---|---|---|
$sum | 计算总和。 | db.mycol.aggregate([{\(group : {_id : "\)by_user", num_tutorial : {\(sum : "\)likes"}}}]) |
$avg | 计算平均值 | db.mycol.aggregate([{\(group : {_id : "\)by_user", num_tutorial : {\(avg : "\)likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{\(group : {_id : "\)by_user", num_tutorial : {\(min : "\)likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{\(group : {_id : "\)by_user", num_tutorial : {\(max : "\)likes"}}}]) |
$push | 在结果文档中插入值到一个数组中。 | db.mycol.aggregate([{\(group : {_id : "\)by_user", url : {\(push: "\)url"}}}]) |
$addToSet | 在结果文档中插入值到一个数组中,但不创建副本。 | db.mycol.aggregate([{\(group : {_id : "\)by_user", url : {\(addToSet : "\)url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{\(group : {_id : "\)by_user", first_url : {\(first : "\)url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{\(group : {_id : "\)by_user", last_url : {\(last : "\)url"}}}]) |
三、数据模拟
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":"商品鼠标 1","price":50,num:1})
db.order_item.insert({"order_id":"1","title":"商品键盘 2","price":50,num:1})
db.order_item.insert({"order_id":"1","title":"商品键盘 3","price":0,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"}}
}
]);
六、 $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"
}
},
{
$project:{ trade_no:1, all_price:1,items:1 }
}
]);