MongoDB Aggregations
- 聚合框架
- $project
- $match
- $limit
- $skip
- $unwind
- $group
- $sort
- $out
- $count
- References
聚合框架
聚合框架是一种查询语言,可用于转换和组合来自多个文档的数据,以生成任何单个文档中都无法获得的新信息。
MongoDB中的聚合框架类似于SQL 中的GROUP BY和HAVING。
聚合框架过在一个数组中指定一系列操作并在一个调用中处理它,使得任务数据库搜索更加容易和高效。
聚合框架定义了一个聚合管道,其中管道中每个步骤的输出为下一步提供输入。
管道中的每个步骤都对输入文档执行一个操作,以转换输入并生成输出文档。
管道通过过滤、投影、分组、排序、限制和跳过等操作来处理文档流。
相同的操作可以在管道中以任何顺序重复多次。
$project
$project提取子文档的组件,重命名组件,并对组件执行操作。
选择每个部门的名称,跳过文档标识:
db.department.aggregate([ {"$project":{"name":1,"_id":0}} ])
选择每个部门的名称,并将其与代码连接起来:
db.document.aggregate([{"$project":{"Name and code":{"$concat":["$name","-","$code"]}}}])
Name and code是我们创建的$ project名,后面括号里的内容是$ project要进行的操作。
选择一个部门名称和10%的预算:
db.department.aggregate([ {"$project":{"name":1,
"10% of budget":{"$multiply":["$budget",0.1]},
"_id":0}
}
]
)
$match
$match操作选择了满足给定条件的文档。
找到预算> 10000的部门名称和代码:
db.department.aggregate([ {"$match":{"budget":{$gt:10000}}},
{"$project":{"name":1,"code":1,"_id":0}} ])
$limit
$limit通过管道传递给定数量的文档。
找到预算>1000的第一份文件:
db.department.aggregate([ {"$match":{"budget":{"$gt":10000}}},
{"$limit":1} ]
limit:1代表第一,limit:2代表前2。
$skip
$skip从管道中消除给定数量的文档。
列出所有预算超过10000的文档,除了第一个:
db.department.aggregate([ {"$match":{"budget":{"$gt":10000}}},
{"$skip":1}] )
注意skip与limit之间的区别,在什么情况下使用哪个。
$unwind
$unwind为给定数组的每个元素创建一个单独的文档。
数组的每个元素都复制一个文档,也就是说数组没有嵌套。
对于部门的每个系和每门课程创建一个单独的文件,只列出课程:
db.department.aggregate([ {"$unwind":"$courses"},
{"$project":{"courses":1,"_id":0}} ])
找到所有12学分的课程:
db.department.aggregate([ {"$unwind":"$courses"},
{"$project":{"courses":1,"_id":0}},
{"$match":{"courses.credits":12}} ])
$group
$group对文档进行分组,并对每个组应用聚合函数。
按total_staff_number对文档进行分组,并列出total_staff_number的不同值
:
db.department.aggregate([ {"$group":{"_id":"$total_staff_number"}} ])
输出结果如下:
{ "_id" : 5 }
{ "_id" : 25 }
按照上面的方法进行分组,并将_id重命名为total_staff_number:
db.department.aggregate([ {"$group":{"_id":"$total_staff_number"}},
{"$project":{"total_staff_number":"$_id","_id":0}} ])
{ "total_staff_number" : 5 }
{ "total_staff_number" : 25 }
按total_staff_number和预算对文件进行分组:
db.department.aggregate([ {"$group":{"_id":{"total_staff_number":"$total_staff_number",
"budget":"$budget"},
{ "_id" : { "total_staff_number" : 5, "budget" : 10000 } }
{ "_id" : { "total_staff_number" : 25, "budget" : 100000 } }
{ "_id" : { "total_staff_number" : 25, "budget" : 1000000 } }
根据total_staff_number和每个组的平均预算对文件进行分组:
db.department.aggregate([ {"$group":{"_id":"$total_staff_number",
"largest budget":{"$avg":"$budget"}}} ])
avg代表平均,同理如果找最大或最小的工资就用max或者min。
$sort
$sort对文档进行排序。
显示最大预算的部门名称,显示部门名称及其预算:
db.department.aggregate([ {"$project":{"name":1,"budget":1,"_id":0}},
{"$sort":{"budget":-1}},
{"$limit":1} ])
这里-1代表降序排列,最上面的是最大的,之后再limit 1,就把最大的筛选出来了。
同理1代表升序。
将文档按total_staff_number分组,统计每组中部门总数将结果按照部门总数降序排列:
db.department.aggregate([ {"$group":{"_id":"$total_staff_number",
"total departments":{"$sum":1}}},
{"$sort":{"total departments":-1}} ])
输出结果:
{ "_id" : 25, "total departments" : 2 }
{ "_id" : 5, "total departments" : 1 }
$out
$out将处理结果保存在集合中。
找到total_staff_number不同值的总数:
db.department.aggregate([ {"$group":{"_id":"$total_staff_number"}},
{"$out":"total_distinct"}])
db.total_distinct.count()
/*用完删除*/
db.total_distinct.drop()
$count
$count计算管道中文档的总数。
列出所有课程的代码:
db.department.aggregate([ {"$unwind":"$courses"},
{"$project":{"code":"$courses.code","_id":0}},
{"$count":"Total number of courses"} ])
MongoDB中的aggregate项目练习:
References
- Chodorow K. MongoDB The De?nitive Guide, O’Reilly, 2013.
- Banker K., Bakkum P., Verch S., Garret D., Hawkins T., MongoDB in Action, 2nd ed., Manning Publishers, 2016.