MongoDB 聚合管道(AggregationPipeline)
使用聚合管道可以对集合中的文档进行变换和组合。实际项目应用主要是表关联查询、数据的统计。
MongoDB 中使用 db.COLLECTION_NAME.aggregate([{<stage>},...]) 方法 来构建和使用聚合管道。下面是官网给的实例,感受一下聚合管道的用法。
第一个步时查找orders集合中status为A的数据,第二步是根据cust_id做了一个分组,第三步是将属于同一个分组中的amount进行求和后给total字段赋值
MongoDB Aggregation 管道常用的操作符与表达式
MongoDB Aggregation 管道常用的操作符
$project :增加、删除、重命名字段
$match:条件匹配。只满足条件的文档才能进入下 一阶段
$limit 限制结果的数量
$skip 跳过文档的数量
$sort 条件排序。
$group 条件组合结果 统计
$lookup 操作符 用以引入其它集合的数 据 (表关联查询)
SQL 和 NOSQL 对比:
MongoDB Aggregation 管道常用的表达式
管道操作符作为“键”,所对应的“值”叫做管道表达式。例如{$match:{status:"A"}},$match 称为管道操作符,而 status:"A"称为管道表达式, 是管道操作符的操作数(Operand)。
每个管道表达式是一个文档结构,它是由字段名、字段值、和一些表达式操作符组成的。
数据模拟
在演示每个操作符的使用之前,先要有数据,这里我们先创建一个数据库()和一个order集合,order_item集合来进行演示操作
先使用数据库aggregation(使用及创建)
use aggregation
然后直接插入数据的方式来创建集合
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() 方法中的参数。比如下面找出all_price字段的值大于等于90的数据
db.order.aggregate([ { $project:{ order_id:1,trade_no:1, all_price:1 } }, { $match:{"all_price":{$gte:90}} } ])
$group
将集合中的文档进行分组,可用于统计结果。比如:统计每个订单的订单数量,按照订单号分组
db.order_item.aggregate( [ { $group: {_id: "$order_id", total: {$sum: "$num"}} } ] )
查询结果显示order_id为3的总数total有6个.......
$sort
将集合中的文档进行排序
db.order.aggregate([ { $project:{ trade_no:1, all_price:1 } }, { $match:{"all_price":{$gte:90}} }, { $sort:{"all_price":1} } ])
$limit 限制结果的数量
这个操作符在实际项目中可以用于分页操作中查找多少条数据可以结合$skip来完成分页功能
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 表关联
比如我想查找order集合和order_item集合,然后得出下面这样的结果
[{ Order_id:'1', Trade_no:'', Items:[{ Title:'鼠标', Price: 20 }, { Title: '键盘', Price: 20 }] }, { Order_id: '2', Trade_no: '', Items: [{ Title: '鼠标', Price: 20 }, { Title: '键盘', Price: 20 }] }]
那么我们可以使用$lookup关联查询
db.order.aggregate([ { $lookup: { from: "order_item", localField: "order_id", foreignField: "order_id", as: "items" } } ])
跟其他操作符来一起使用,比如$match,找出all_price字段大于等于90的数据
db.order.aggregate([ { $lookup: { from: "order_item", localField: "order_id", foreignField: "order_id", as: "items" } }, { $match:{"all_price":{$gte:90}} } ])