MongoDB的高级查询aggregate聚合管道
https://mongodb.net.cn/manual/aggregation/
一、MongoDB 聚合管道(Aggregation Pipeline)
- 使用聚合管道可以对集合中的文档进行变换和组合。
- 实际项目:表关联查询、数据的统计。 MongoDB 中使用
db.COLLECTION_NAME.aggregate([{},...])方法来构建和使用聚合管道。
先看下官网给的实例,感受一下聚合管道的用法。

二、MongoDB Aggregation 管道操作符与表达式
| 管道操作符 | Description |
|---|---|
| $project | 增加、删除、重命名字段(查询结果字段限制) |
| $match | 条件匹配。只满足条件的文档才能进入下一阶段 |
| $limit | 限制结果的数量 |
| $skip | 跳过文档的数量 |
| $sort | 条件排序。 |
| $group | 条件组合结果统计 |
| $lookup | 引入其它集合的数 据 (表关联查询) |
SQL 和 NOSQL 对比:
| SQL | NOSQL |
|---|---|
| WHERE | $match |
| GROUP BY | $group |
| HAVING | $match |
| SELECT | $project |
| ORDER BY | $sort |
| LIMIT | $limit |
| SUM() | $sum |
| COUNT() | $sum |
| join | $lookup |
管道表达式:管道操作符作为“键”,所对应的“值”叫做管道表达式。
例如:
{ $match: {status: "A" } }
$match称为管道操作符,而status: "A"称为管道表达式, 是管道操作符的操作数(Operand)。- 每个管道表达式是一个文档结构,它是由字段名、字段值、和一些表达式操作符组成的。
| 常用表达式操作符 | Description |
|---|---|
| $addToSet | 将文档指定字段的值去重 |
| $max | 文档指定字段的最大值 |
| $min | 文档指定字段的最小值 |
| $sum | 文档指定字段求和 |
| $avg | 文档指定字段求平均 |
| $gt | 大于给定值 |
| $lt | 小于给定值 |
| $eq | 等于给定值 |
三、数据模拟
// 订单表
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 字段
# 1代表要此字段,0就是不要
db.order.aggregate([
{
$project: { trade_no: 1, all_price: 1 }
}
])
五、$match
作用:用于过滤文档。用法类似于 find() 方法中的参数。
# 上面结果再查all_price >= 90的记录
db.order.aggregate([
{
$project:{ trade_no: 1, all_price: 1 }
},
{
$match:{"all_price": { $gte: 90 }}
}
])
六、$group
- 将集合中的文档(按订单编号)进行分组,可用于统计结果。
- 统计每个订单的订单数量,按照订单号分组
#_id固定写法,这里表示按order_id分组
db.order_item.aggregate([
{
$group: { _id: "$order_id", total: { $sum: "$num" } }
}
])
七、$sort
将集合中的文档进行排序。
-1倒序,1顺序
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 表关联
#订单表在订单项表有多个记录,通过order_id关联,关联查询出来的记录数组名为items
db.order.aggregate([
{
$lookup: {
from: "order_item",
localField: "order_id", foreignField: "order_id", as: "items"
}
}
])结果
// 第一条
{
"_id": ObjectId("5b743d8c2c327f8d1b360540"),
"order_id": "1",
"uid": 10,
"trade_no": "111",
"all_price": 100,
"all_num": 2,
"items": [
{
"_id": ObjectId("5b743d9c2c327f8d1b360543"),
"order_id": "1",
"title": "商品鼠标 1",
"price": 50,
"num": 1
},
{
"_id": ObjectId("5b743da12c327f8d1b360544"),
"order_id": "1",
"title": "商品键盘 2",
"price": 50,
"num": 1
},
{
"_id": ObjectId("5b74f457089f78dc8f0a4f3b"),
"order_id": "1",
"title": "商品键盘 3",
"price": 0,
"num": 1
}
]
}
// 第二条
{
"_id": ObjectId("5b743d902c327f8d1b360541"),
"order_id": "2",
"uid": 7,
"trade_no": "222",
"all_price": 90,
"all_num": 2,
"items": [
{
"_id": ObjectId("5b743da52c327f8d1b360545"),
"order_id": "2",
"title": "牛奶",
"price": 50,
"num": 1
},
{
"_id": ObjectId("5b743da92c327f8d1b360546"),
"order_id": "2",
"title": "酸奶",
"price": 40,
"num": 1
}
]
}
// 第三条
{
"_id": ObjectId("5b743d962c327f8d1b360542"),
"order_id": "3",
"uid": 9,
"trade_no": "333",
"all_price": 20,
"all_num": 6,
"items": [
{
"_id": ObjectId("5b743dad2c327f8d1b360547"),
"order_id": "3",
"title": "矿泉水",
"price": 2,
"num": 5
},
{
"_id": ObjectId("5b743dff2c327f8d1b360548"),
"order_id": "3",
"title": "毛巾",
"price": 10,
"num": 1
}
]
}上面结果再查all_price >= 90的记录
db.order.aggregate([
{
$lookup:
{
from: "order_item",
localField: "order_id", foreignField: "order_id", as: "items"
}
},
{
$match: { "all_price": { $gte: 90 } }
}
])结果
// 第一条
{
"_id": ObjectId("5b743d8c2c327f8d1b360540"),
"order_id": "1",
"uid": 10,
"trade_no": "111",
"all_price": 100,
"all_num": 2,
"items": [
{
"_id": ObjectId("5b743d9c2c327f8d1b360543"),
"order_id": "1",
"title": "商品鼠标 1",
"price": 50,
"num": 1
},
{
"_id": ObjectId("5b743da12c327f8d1b360544"),
"order_id": "1",
"title": "商品键盘 2",
"price": 50,
"num": 1
},
{
"_id": ObjectId("5b74f457089f78dc8f0a4f3b"),
"order_id": "1",
"title": "商品键盘 3",
"price": 0,
"num": 1
}
]
}
// 第二条
{
"_id": ObjectId("5b743d902c327f8d1b360541"),
"order_id": "2",
"uid": 7,
"trade_no": "222",
"all_price": 90,
"all_num": 2,
"items": [
{
"_id": ObjectId("5b743da52c327f8d1b360545"),
"order_id": "2",
"title": "牛奶",
"price": 50,
"num": 1
},
{
"_id": ObjectId("5b743da92c327f8d1b360546"),
"order_id": "2",
"title": "酸奶",
"price": 40,
"num": 1
}
]
}再次对字段限制,倒序
db.order.aggregate([
{
$lookup:
{
from: "order_item",
localField: "order_id", foreignField: "order_id", as: "items"
}
},
{
$project:{ trade_no:1, all_price:1,items:1 }
},
{
$match:{"all_price":{$gte:90}}
},
{
$sort:{"all_price":-1}
}
])结果
// 1
{
"_id": ObjectId("5b743d8c2c327f8d1b360540"),
"trade_no": "111",
"all_price": 100,
"items": [
{
"_id": ObjectId("5b743d9c2c327f8d1b360543"),
"order_id": "1",
"title": "商品鼠标 1",
"price": 50,
"num": 1
},
{
"_id": ObjectId("5b743da12c327f8d1b360544"),
"order_id": "1",
"title": "商品键盘 2",
"price": 50,
"num": 1
},
{
"_id": ObjectId("5b74f457089f78dc8f0a4f3b"),
"order_id": "1",
"title": "商 品键盘 3",
"price": 0,
"num": 1
}
]
}
// 2
{
"_id": ObjectId("5b743d902c327f8d1b360541"),
"trade_no": "222",
"all_price": 90,
"items": [
{
"_id": ObjectId("5b743da52c327f8d1b360545"),
"order_id": "2",
"title": "牛奶",
"price": 50,
"num": 1
},
{
"_id": ObjectId("5b743da92c327f8d1b360546"),
"order_id": "2",
"title": "酸奶",
"price": 40,
"num": 1
}
]
}
Ценники на вывоз мусора сейчас космос, любые лайфхаки по экономии в тему.
1xbet onlayn kazino platforması ilə vaxtınızı daha səmərəli və maraqlı keçirin. Saytın canlı kazino bölməsi istifadəçilərə fərqli bir dünya təklif edir. Burada canlı dilerli kazino oyunlarının hər bir növünü sınaqdan keçirə bilərsiniz. Krupyelərin peşəkarlığı oyunun dinamikasını və marağını artırır. Müntəzəm olaraq yenilənən oyun siyahısı cansıxıcılığa yol vermir. Hesabınızı artırmaq üçün onlarla fərqli və etibarlı üsul mövcuddur. Qazanılan pullar cəmi bir neçə dəqiqə ərzində şəxsi hesabınıza köçürülür. Aktiv fəaliyyətinizə görə fərdi bonuslar və hədiyyələr qazana bilərsiniz. Dəstək xidməti həm çat, həm də e-poçt vasitəsilə kömək göstərir. 1xbet ailəsinə qoşulun və böyük uduşlar üçün ilk addımı atın. onlayn kazino
我一直梦想, 看到你们相册那样的地方。真棒。
我喜欢, 这里分享真实经验。你的项目 就是 属于这里的。请继续。
我热爱这样的想法, 去那么多国家。真的很鼓舞。
能感受到热爱。继续保持 感受。
我关注这样的资源, 写得很实在。你的网站 就是 属于这里的。加油。
1
1
1