高级查询 聚合管道(aggregate pipeline)

使用聚合管道可以对集合中的文档进行变换和组合

用于表关联查询、数据的统计等。

MongoDB 使用 db.COLLECTION_NAME.aggregate([{<stage>} , ... ]) 方法来构建和使用聚合管道。

MongoDB Aaggregation 管道操作符与表达式:

① $project:增加、删除、重命名字段

② $match:条件匹配,只有满足条件的文档才能进入下一阶段

③ $limit:限制结果的数量

④ $skip:跳过文档的数量

⑤ $sort:条件排序

⑥ $lookup:用以引入其他集合的数据(表关联查询)

管道表达式:

管道操作符作为“键”,所对应的“值”叫做管道表达式

例如 :{$match:{status:"A"}},$match 称为管道操作符,而status:"A"称为管道表达式,是管道操作符的操作数。
每个管道表达式是一个文档结构,它是由字段名,字段值,和一些表达式操作符组成的。

 先建立两个数据库:订单 order 和 商品 orderItem

> use order
switched to db order
> db.order.find()
{ "_id" : ObjectId("5eec580554173c45e32c1d75"), "order_id" : 1, "trade_sum" : 10, "all_price" : 101, "all_num" : 11 }
{ "_id" : ObjectId("5eec580554173c45e32c1d76"), "order_id" : 2, "trade_sum" : 20, "all_price" : 102, "all_num" : 12 }
{ "_id" : ObjectId("5eec580554173c45e32c1d77"), "order_id" : 3, "trade_sum" : 30, "all_price" : 103, "all_num" : 13 }
{ "_id" : ObjectId("5eec580554173c45e32c1d78"), "order_id" : 4, "trade_sum" : 40, "all_price" : 104, "all_num" : 14 }
{ "_id" : ObjectId("5eec580554173c45e32c1d79"), "order_id" : 5, "trade_sum" : 50, "all_price" : 105, "all_num" : 15 }
>

  

> use orderItem
switched to db orderItem
> db.orderItem.find()
{ "_id" : ObjectId("5eec590f54173c45e32c1d7a"), "order_id" : 1, "title" : "order_id=1,item1", "price" : 11, "num" : 4 }
{ "_id" : ObjectId("5eec590f54173c45e32c1d7b"), "order_id" : 1, "title" : "order_id=1,item2", "price" : 12, "num" : 5 }
{ "_id" : ObjectId("5eec590f54173c45e32c1d7c"), "order_id" : 1, "title" : "order_id=1,item3", "price" : 13, "num" : 6 }
{ "_id" : ObjectId("5eec596154173c45e32c1d7d"), "order_id" : 2, "title" : "order_id=2,item1", "price" : 16, "num" : 6 }
{ "_id" : ObjectId("5eec596154173c45e32c1d7e"), "order_id" : 2, "title" : "order_id=2,item2", "price" : 17, "num" : 7 }
{ "_id" : ObjectId("5eec596154173c45e32c1d7f"), "order_id" : 2, "title" : "order_id=2,item3", "price" : 18, "num" : 8 }
{ "_id" : ObjectId("5eec596154173c45e32c1d80"), "order_id" : 2, "title" : "order_id=2,item4", "price" : 19, "num" : 9 }
{ "_id" : ObjectId("5eec599454173c45e32c1d81"), "order_id" : 3, "title" : "order_id=3,item1", "price" : 21, "num" : 8 }
{ "_id" : ObjectId("5eec599454173c45e32c1d82"), "order_id" : 3, "title" : "order_id=3,item2", "price" : 22, "num" : 9 }
{ "_id" : ObjectId("5eec599454173c45e32c1d83"), "order_id" : 3, "title" : "order_id=3,item3", "price" : 23, "num" : 10 }
{ "_id" : ObjectId("5eec599454173c45e32c1d84"), "order_id" : 3, "title" : "order_id=3,item4", "price" : 24, "num" : 11 }
{ "_id" : ObjectId("5eec59cc54173c45e32c1d85"), "order_id" : 4, "title" : "order_id=4,item1", "price" : 25, "num" : 11 }
{ "_id" : ObjectId("5eec59cc54173c45e32c1d86"), "order_id" : 4, "title" : "order_id=4,item2", "price" : 26, "num" : 12 }
{ "_id" : ObjectId("5eec59cc54173c45e32c1d87"), "order_id" : 4, "title" : "order_id=4,item3", "price" : 27, "num" : 13 }
{ "_id" : ObjectId("5eec59cc54173c45e32c1d88"), "order_id" : 4, "title" : "order_id=4,item4", "price" : 28, "num" : 14 }
{ "_id" : ObjectId("5eec59cc54173c45e32c1d89"), "order_id" : 4, "title" : "order_id=4,item5", "price" : 29, "num" : 15 }
{ "_id" : ObjectId("5eec5a0154173c45e32c1d8a"), "order_id" : 5, "title" : "order_id=5,item1", "price" : 31, "num" : 15 }
{ "_id" : ObjectId("5eec5a0154173c45e32c1d8b"), "order_id" : 5, "title" : "order_id=5,item2", "price" : 32, "num" : 16 }
>

通过 $project 操作符,修改文档的结构,查找 order 只返回 trade_sum 和 all_price字段:

> use order
switched to db order
> db.order.aggregate([
... {
... $project:{trade_sum:1,all_price:1}
... }
... ]}
2020-06-19T14:28:37.794+0800 E  QUERY    [js] uncaught exception: SyntaxError: missing ) after argument list :
@(shell):5:1
> db.order.aggregate([ { $project:{trade_sum:1,all_price:1} } ])
{ "_id" : ObjectId("5eec580554173c45e32c1d75"), "trade_sum" : 10, "all_price" : 101 }
{ "_id" : ObjectId("5eec580554173c45e32c1d76"), "trade_sum" : 20, "all_price" : 102 }
{ "_id" : ObjectId("5eec580554173c45e32c1d77"), "trade_sum" : 30, "all_price" : 103 }
{ "_id" : ObjectId("5eec580554173c45e32c1d78"), "trade_sum" : 40, "all_price" : 104 }
{ "_id" : ObjectId("5eec580554173c45e32c1d79"), "trade_sum" : 50, "all_price" : 105 }
>

通过$match ,过滤文档,

> db.order.aggregate([
... {
... $project:{trade_sum:1,all_price:1}
... }
... ,
... {
... $match:{all_price:{$gte:103}}
... }
... ])
{ "_id" : ObjectId("5eec580554173c45e32c1d77"), "trade_sum" : 30, "all_price" : 103 }
{ "_id" : ObjectId("5eec580554173c45e32c1d78"), "trade_sum" : 40, "all_price" : 104 }
{ "_id" : ObjectId("5eec580554173c45e32c1d79"), "trade_sum" : 50, "all_price" : 105 }
>

通过 $group 将集合中的文档进行分组,可用于统计结果,统计每个订单的订单数量,按照订单号分组:

> db.orderItem.aggregate(
... [
...   {$group:{ID:"$order_id",total:{$sum:"$num"}} }
... ]
... )
2020-06-19T14:38:28.146+0800 E  QUERY    [js] uncaught exception: Error: command failed: {
        "ok" : 0,
        "errmsg" : "The field 'ID' must be an accumulator object",
        "code" : 40234,
        "codeName" : "Location40234"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:583:17
assert.commandWorked@src/mongo/shell/assert.js:673:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1012:12
@(shell):1:1
> db.orderItem.aggregate( [   {$group:{_id:"$order_id",total:{$sum:"$num"}} } ] )
{ "_id" : 2, "total" : 30 }
{ "_id" : 3, "total" : 38 }
{ "_id" : 1, "total" : 15 }
{ "_id" : 5, "total" : 31 }
{ "_id" : 4, "total" : 65 }
>

通过 $sort 将集合中的文档进行排序:

> db.order.aggregate([
... {
...   $project:{trade_sum:1,all_price:1}
... },
... {
...   $match:{all_price:{$gte:104}}
... },
... {
...   $sort:{all_price:-1}
... }
... ])
{ "_id" : ObjectId("5eec580554173c45e32c1d79"), "trade_sum" : 50, "all_price" : 105 }
{ "_id" : ObjectId("5eec580554173c45e32c1d78"), "trade_sum" : 40, "all_price" : 104 }
>

¥$limit 限制数量:

> db.order.aggregate([
... {
...   $project:{trade_sum:1,all_price:1}
... },
... {
...   $match:{all_price:{$gte:102}}
... },
... {
...   $sort:{all_price:-1}
... },
... {
...   $limit:2
... }
... ])
{ "_id" : ObjectId("5eec580554173c45e32c1d79"), "trade_sum" : 50, "all_price" : 105 }
{ "_id" : ObjectId("5eec580554173c45e32c1d78"), "trade_sum" : 40, "all_price" : 104 }
>

$skip 跳过某一页,从指定记录开始查询:

> db.order.aggregate([
... {
...   $project:{trade_sum:1,all_price:1}
... },
... {
...   $sort:{all_price:1}
... },
... {
...   $skip:3
... }
... ])
{ "_id" : ObjectId("5eec580554173c45e32c1d78"), "trade_sum" : 40, "all_price" : 104 }
{ "_id" : ObjectId("5eec580554173c45e32c1d79"), "trade_sum" : 50, "all_price" : 105 }
>

$lookup 表关联:

> show dbs
admin   0.000GB
config  0.000GB
hello   0.000GB
local   0.000GB
> use hello
switched to db hello
> show collections
order
orderItem
user
> db.order.find()
{ "_id" : ObjectId("5eec63141f939bf9cce25f7b"), "order_id" : 1, "trade_sum" : 101, "all_price" : 100, "all_num" : 11 }
{ "_id" : ObjectId("5eec63141f939bf9cce25f7c"), "order_id" : 2, "trade_sum" : 102, "all_price" : 200, "all_num" : 12 }
{ "_id" : ObjectId("5eec63141f939bf9cce25f7d"), "order_id" : 3, "trade_sum" : 103, "all_price" : 300, "all_num" : 13 }
{ "_id" : ObjectId("5eec63141f939bf9cce25f7e"), "order_id" : 4, "trade_sum" : 104, "all_price" : 400, "all_num" : 14 }
{ "_id" : ObjectId("5eec63141f939bf9cce25f7f"), "order_id" : 5, "trade_sum" : 105, "all_price" : 500, "all_num" : 15 }
> db.orderItem.find()
{ "_id" : ObjectId("5eec638c1f939bf9cce25f80"), "order_id" : 1, "title" : "orderId=1,from item1", "price" : 10, "num" : 6 }
{ "_id" : ObjectId("5eec638c1f939bf9cce25f81"), "order_id" : 1, "title" : "orderId=1,from item2", "price" : 20, "num" : 7 }
{ "_id" : ObjectId("5eec638c1f939bf9cce25f82"), "order_id" : 1, "title" : "orderId=1,from item3", "price" : 30, "num" : 8 }
{ "_id" : ObjectId("5eec63c71f939bf9cce25f83"), "order_id" : 2, "title" : "orderId=2,from item1", "price" : 12, "num" : 11 }
{ "_id" : ObjectId("5eec63c71f939bf9cce25f84"), "order_id" : 2, "title" : "orderId=2,from item2", "price" : 24, "num" : 12 }
{ "_id" : ObjectId("5eec63c71f939bf9cce25f85"), "order_id" : 2, "title" : "orderId=2,from item3", "price" : 36, "num" : 13 }
{ "_id" : ObjectId("5eec63f41f939bf9cce25f86"), "order_id" : 3, "title" : "orderId=3,from item1", "price" : 15, "num" : 18 }
{ "_id" : ObjectId("5eec63f41f939bf9cce25f87"), "order_id" : 3, "title" : "orderId=3,from item2", "price" : 30, "num" : 19 }
{ "_id" : ObjectId("5eec63f41f939bf9cce25f88"), "order_id" : 3, "title" : "orderId=3,from item3", "price" : 45, "num" : 20 }
{ "_id" : ObjectId("5eec63f41f939bf9cce25f89"), "order_id" : 3, "title" : "orderId=3,from item4", "price" : 60, "num" : 21 }
{ "_id" : ObjectId("5eec63f41f939bf9cce25f8a"), "order_id" : 3, "title" : "orderId=3,from item5", "price" : 75, "num" : 22 }
{ "_id" : ObjectId("5eec64241f939bf9cce25f8b"), "order_id" : 4, "title" : "orderId=4,from item1", "price" : 20, "num" : 28 }
{ "_id" : ObjectId("5eec64241f939bf9cce25f8c"), "order_id" : 4, "title" : "orderId=4,from item2", "price" : 40, "num" : 29 }
{ "_id" : ObjectId("5eec644b1f939bf9cce25f8d"), "order_id" : 5, "title" : "orderId=5,from item1", "price" : 24, "num" : 33 }
{ "_id" : ObjectId("5eec644b1f939bf9cce25f8e"), "order_id" : 5, "title" : "orderId=5,from item2", "price" : 48, "num" : 34 }
{ "_id" : ObjectId("5eec644b1f939bf9cce25f8f"), "order_id" : 5, "title" : "orderId=5,from item3", "price" : 72, "num" : 35 }
{ "_id" : ObjectId("5eec644b1f939bf9cce25f90"), "order_id" : 5, "title" : "orderId=5,from item4", "price" : 96, "num" : 36 }
> db.order.aggregate([
... {
...   $lookup:{
...              from:"orderItem",
...              localField:"order_id",
...              foreignField:"order_id",
...              as:"items"
...           }
... }
... ])
{ "_id" : ObjectId("5eec63141f939bf9cce25f7b"), "order_id" : 1, "trade_sum" : 101, "all_price" : 100, "all_num" : 11,
"items" : [ { "_id" : ObjectId("5eec638c1f939bf9cce25f80"), "order_id" : 1, "title" : "orderId=1,from item1", "price" : 10, "num" : 6 },
{ "_id" : ObjectId("5eec638c1f939bf9cce25f81"), "order_id" : 1, "title" : "orderId=1,from item2", "price" : 20, "num" : 7 },
{ "_id" : ObjectId("5eec638c1f939bf9cce25f82"), "order_id" : 1, "title" : "orderId=1,from item3", "price" : 30, "num" : 8 }
            ] } { "_id" : ObjectId("5eec63141f939bf9cce25f7c"), "order_id" : 2, "trade_sum" : 102, "all_price" : 200, "all_num" : 12,
      "items" : [ { "_id" : ObjectId("5eec63c71f939bf9cce25f83"), "order_id" : 2, "title" : "orderId=2,from item1", "price" : 12, "num" : 11 },
             { "_id" : ObjectId("5eec63c71f939bf9cce25f84"), "order_id" : 2, "title" : "orderId=2,from item2", "price" : 24, "num" : 12 },
             { "_id" : ObjectId("5eec63c71f939bf9cce25f85"), "order_id" : 2, "title" : "orderId=2,from item3", "price" : 36, "num" : 13 }
            ] } { "_id" : ObjectId("5eec63141f939bf9cce25f7d"), "order_id" : 3, "trade_sum" : 103, "all_price" : 300, "all_num" : 13,
      "items" : [ { "_id" : ObjectId("5eec63f41f939bf9cce25f86"), "order_id" : 3, "title" : "orderId=3,from item1", "price" : 15, "num" : 18 },
             { "_id" : ObjectId("5eec63f41f939bf9cce25f87"), "order_id" : 3, "title" : "orderId=3,from item2", "price" : 30, "num" : 19 },
           { "_id" : ObjectId("5eec63f41f939bf9cce25f88"), "order_id" : 3, "title" : "orderId=3,from item3", "price" : 45, "num" : 20 },
             { "_id" : ObjectId("5eec63f41f939bf9cce25f89"), "order_id" : 3, "title" : "orderId=3,from item4", "price" : 60, "num" : 21 },
             { "_id" : ObjectId("5eec63f41f939bf9cce25f8a"), "order_id" : 3, "title" : "orderId=3,from item5", "price" : 75, "num" : 22 }
           ] } { "_id" : ObjectId("5eec63141f939bf9cce25f7e"), "order_id" : 4, "trade_sum" : 104, "all_price" : 400, "all_num" : 14,
      "items" : [ { "_id" : ObjectId("5eec64241f939bf9cce25f8b"), "order_id" : 4, "title" : "orderId=4,from item1", "price" : 20, "num" : 28 },
             { "_id" : ObjectId("5eec64241f939bf9cce25f8c"), "order_id" : 4, "title" : "orderId=4,from item2", "price" : 40, "num" : 29 }
            ] } { "_id" : ObjectId("5eec63141f939bf9cce25f7f"), "order_id" : 5, "trade_sum" : 105, "all_price" : 500, "all_num" : 15,
       "items" : [ { "_id" : ObjectId("5eec644b1f939bf9cce25f8d"), "order_id" : 5, "title" : "orderId=5,from item1", "price" : 24, "num" : 33 },
             { "_id" : ObjectId("5eec644b1f939bf9cce25f8e"), "order_id" : 5, "title" : "orderId=5,from item2", "price" : 48, "num" : 34 },
             { "_id" : ObjectId("5eec644b1f939bf9cce25f8f"), "order_id" : 5, "title" : "orderId=5,from item3", "price" : 72, "num" : 35 },
             { "_id" : ObjectId("5eec644b1f939bf9cce25f90"), "order_id" : 5, "title" : "orderId=5,from item4", "price" : 96, "num" : 36 }
             ] } >

  

原文地址:https://www.cnblogs.com/shanlu0000/p/13163277.html