MongoDB 高级查询 aggregate 聚合管道

Julia ·
更新时间:2024-11-10
· 904 次阅读

1. MongoDB 聚合管道简介

使用聚合管道可以对集合中的文档进行变换和组合,常用于多表关联查询、数据的统计。

db.COLLECTION_NAME.aggregate() 方法用来构建和使用聚合管道,下图是官网给的实例,可以看出来聚合管道的用法还是比较简单的。

  2. MongoDB Aggregation 管道操作符与表达式

常用的管道操作符有以下这些:

MySQL 和 MongoDB 的聚合对比: 管道操作符作为“键”,所对应的“值”叫做管道表达式,如 {$match:{status:"A"}},$match 称为管道操作符,而 status:"A"称为管道表达式,每个管道表达式是一个文档结构,它是由字段名、字段值、和一些表达式操作符组成的,常用的表达式操作符有以下这些。 3. 模拟数据

为了说明每个管道操作符的作用,将以下面数据为参考,分别有order和order_item两个集合。

order集合里的数据

{ "_id": ObjectId("5e6f15c1eb57cc45bde8130b"), "order_id": "1", "uid": 10, "trade_no": "111", "all_price": 100, "all_num": 2 } { "_id": ObjectId("5e6f15cbeb57cc45bde8130c"), "order_id": "2", "uid": 7, "trade_no": "222", "all_price": 90, "all_num": 2 } { "_id": ObjectId("5e6f15d4eb57cc45bde8130d"), "order_id": "3", "uid": 9, "trade_no": "333", "all_price": 20, "all_num": 6 }

order_item集合里的数据

{ "_id": ObjectId("5e6f15dbeb57cc45bde8130e"), "order_id": "1", "title": "商品鼠标 1", "price": 50, "num": 1 } { "_id": ObjectId("5e6f15e2eb57cc45bde8130f"), "order_id": "1", "title": "商品键盘 2", "price": 50, "num": 1 } { "_id": ObjectId("5e6f15e8eb57cc45bde81310"), "order_id": "1", "title": "商品键盘 3", "price": 0, "num": 1 } { "_id": ObjectId("5e6f15f1eb57cc45bde81311"), "order_id": "2", "title": "牛奶", "price": 50, "num": 1 } { "_id": ObjectId("5e6f15faeb57cc45bde81312"), "order_id": "2", "title": "酸奶", "price": 40, "num": 1 } { "_id": ObjectId("5e6f1603eb57cc45bde81313"), "order_id": "3", "title": "矿泉水", "price": 2, "num": 5 } { "_id": ObjectId("5e6f160aeb57cc45bde81314"), "order_id": "3", "title": "毛巾", "price": 10, "num": 1 } 4. 管道操作符 $project

修改文档的结构,可以用来重命名、增加或删除文档中的字段。

例:要求查找 order 集合,只返回文档中 trade_no 和 all_price 字段。 db.order.aggregate([ { $project:{ trade_no:1, all_price:1 } } ])

执行结果:

{ "_id" : ObjectId("5e6f15c1eb57cc45bde8130b"), "trade_no" : "111", "all_price" : 100 } { "_id" : ObjectId("5e6f15cbeb57cc45bde8130c"), "trade_no" : "222", "all_price" : 90 } { "_id" : ObjectId("5e6f15d4eb57cc45bde8130d"), "trade_no" : "333", "all_price" : 20 }   5. 管道操作符 $match

用于过滤文档,用法类似于 find() 方法中的参数。

例:要求查找 order 集合,只返回文档中 trade_no 和 all_price 字段,并只显示 all_price 大于等于90的记录。

db.order.aggregate([ { $project: { trade_no: 1, all_price: 1} }, { $match: { "all_price": {$gte: 90} } } ])

执行结果:

{ "_id" : ObjectId("5e6f15c1eb57cc45bde8130b"), "trade_no" : "111", "all_price" : 100 } { "_id" : ObjectId("5e6f15cbeb57cc45bde8130c"), "trade_no" : "222", "all_price" : 90 } 6. 管道操作符 $group

将集合中的文档进行分组,可用于统计结果。

例:统计每个订单的订单数量,按照订单号分组。

db.order_item.aggregate([ { $group: {_id: "$order_id", total: {$sum: "$num"} } } ])

执行结果:

{ "_id" : "2", "total" : 2 } { "_id" : "3", "total" : 6 } { "_id" : "1", "total" : 3 } 7. 管道操作符 $sort  将集合中的文档进行排序。 例:要求查找 order 集合,只返回文档中 trade_no 和 all_price 字段,只显示 all_price 大于等于90的记录,并以all_price进行降序排列。 db.order.aggregate([ { $project: { trade_no: 1, all_price: 1} }, { $match: { "all_price": {$gte: 90} } }, { $sort: {"all_price": -1} } ])

执行结果:

{ "_id" : ObjectId("5e6f15c1eb57cc45bde8130b"), "trade_no" : "111", "all_price" : 100 } { "_id" : ObjectId("5e6f15cbeb57cc45bde8130c"), "trade_no" : "222", "all_price" : 90 } 8. 管道操作符 $limit

限制查询结果的数量。

例:要求查找 order 集合,只返回文档中 trade_no 和 all_price 字段,只显示 all_price 大于等于90的记录,以all_price进行降序排列,并只显示1条记录。

db.order.aggregate([ { $project: { trade_no: 1, all_price: 1} }, { $match: { "all_price": {$gte: 90} } }, { $sort: {"all_price": -1} }, { $limit: 1 } ])

执行结果:

{ "_id" : ObjectId("5e6f15c1eb57cc45bde8130b"), "trade_no" : "111", "all_price" : 100 } 9. 管道操作符 $skip

对查询结果跳过几条记录进行显示。

例:要求查找 order 集合,只返回文档中 trade_no 和 all_price 字段,只显示 all_price 大于等于90的记录,以 all_price 进行降序排列,并跳过1条记录显示其结果。

db.order.aggregate([ { $project: { trade_no: 1, all_price: 1} }, { $match: { "all_price": {$gte: 90} } }, { $sort: {"all_price": -1} }, { $skip: 1 } ])

执行结果:

{ "_id" : ObjectId("5e6f15cbeb57cc45bde8130c"), "trade_no" : "222", "all_price" : 90 }   10. 管道操作符 $lookup

对要查询的结果时行多表关联查询。

例:查询 order 集合,关联到order_item集合,将 order 中 order_id 与 order_item 中order_id 相同的记录显示出来,并将结果取名为 items。

db.order.aggregate([ { $lookup: { from: "order_item", localField: "order_id", foreignField: "order_id", as: "items" } } ])

执行结果:

{ "_id": ObjectId("5e6f15c1eb57cc45bde8130b"), "order_id": "1", "uid": 10, "trade_no": "111", "all_price": 100, "all_num": 2, "items": [ { "_id": ObjectId("5e6f15dbeb57cc45bde8130e"), "order_id": "1", "title": "商品鼠标 1", "price": 50, "num": 1 }, { "_id": ObjectId("5e6f15e2eb57cc45bde8130f"), "order_id": "1", "title": "商品键盘 2", "price": 50, "num": 1 }, { "_id": ObjectId("5e6f15e8eb57cc45bde81310"), "order_id": "1", "title": "商品键盘 3", "price": 0, "num": 1 } ] } { "_id": ObjectId("5e6f15cbeb57cc45bde8130c"), "order_id": "2", "uid": 7, "trade_no": "222", "all_price": 90, "all_num": 2, "items": [ { "_id": ObjectId("5e6f15f1eb57cc45bde81311"), "order_id": "2", "title": "牛奶", "price": 50, "num": 1 }, { "_id": ObjectId("5e6f15faeb57cc45bde81312"), "order_id": "2", "title": "酸奶", "price": 40, "num": 1 } ] } { "_id": ObjectId("5e6f15d4eb57cc45bde8130d"), "order_id": "3", "uid": 9, "trade_no": "333", "all_price": 20, "all_num": 6, "items": [ { "_id": ObjectId("5e6f1603eb57cc45bde81313"), "order_id": "3", "title": "矿泉水", "price": 2, "num": 5 }, { "_id": ObjectId("5e6f160aeb57cc45bde81314"), "order_id": "3", "title": "毛巾", "price": 10, "num": 1 } ] }
作者:aiguangyuan



aggregate MongoDB 管道

需要 登录 后方可回复, 如果你还没有账号请 注册新账号