7.MongoDB系列之聚合框架
1. 管道阶段和可调参数
聚合框架基于管道的概念。他由多个阶段组成,每个阶段都会提供一组按钮或可调参数。每个阶段对其输入执行不同的数据处理任务,并生成文档已作为输出传递到下一阶段。
2. 阶段常见操作
匹配(match)、投射(project)、排序(sort)、跳过(skip)、限制(limit)
如以下命令包括此五阶段
db.getCollection('users').aggregate([
{$match: {age: 42}},
{$sort: {username: 1}},
{$skip: 10},
{$limit: 5},
// 投射其实就是文档的展示信息控制
{$project: {_id: 0, username: 1}}
])
2.1 $unwind对数组进行展开
// 展开前
db.food.find({})
_id fruit
1 (Array) 3 Elements
2 (Array) 3 Elements
3 (Array) 3 Elements
// 展开后
db.food.aggregate([
// $fruit表示取字段fruit展开
{$unwind: "$fruit"}
])
_id fruit
1 apple
1 banana
1 peach
2 apple
2 kumquat
2 orange
3 cherry
3 banana
3 apple
2.2 数组表达式
// 首先插入两个文档
db.blog.insert({'title': 'mongo', 'comments': [{'vote': 100, 'info': 'good'}, {'vote': 110, 'info': 'ok'}]});
db.blog.insert({'title': 'es', 'comments': [{'vote': 90, 'info': 'ok'}, {'vote': 80, 'info': 'bad'}]});
过滤出数组中点赞数大于100的文档
// input表示将要过滤的字段$取字段值 as定义变量 $$用来引入表达式中定义的变量
db.blog.aggregate([
{$match: {}},
{$project: {_id: 0, title: 1, comments: {$filter: {input: "$comments", as: 'comment', cond: {$gte: ['$$comment.vote', 110]}}}}}
])
查询结果如下:
{
"title": "mongo",
"comments": [
{
"vote": 110,
"info": "ok"
}
]
}
{
"title": "es",
"comments": [ ]
}
3. 分组简介
// 先插入文档
db.blog.insert({'title': 'es', 'comments': [{'vote': 80, 'info': 'ok'}, {'vote': 70, 'info': 'bad'}]});
// _id为分组的字段,多个可以{title: '$title', 'comments': '$comments'}
// num名称自定义,可以$sum求和 $avg平均等
db.getCollection('blog').aggregate([
{$group: {_id: 'title', num: {$sum: 1}}}
])
分组结果如下:
{
"_id": "title",
"num": 3
}
db.deal_price.aggregate([
{$match: {'city': {'$in': ['东莞', '佛山', '深圳', '长沙', '中山', '广州', '珠海', '韶关', '合肥', '清远', '惠州']}, 'trade_date': {'$gte': ISODate('2022-06-19')}, 'avg_price': {'$ne': null} }},
{$project: {_id: 0, city: 1, region: 1, district_name: 1, avg_price: 1}},
{$group: {_id: {city: '$city', region: '$region', 'district_name': '$district_name'}, avg_price: {$avg: '$avg_price'}}}
])