MongoDB聚合管道
时间:2022-03-14 03:23
通过上一篇文章中,认识了MongoDB中四个聚合操作,提供基本功能的count、distinct和group,还有可以提供强大功能的mapReduce。
在MongoDB的2.2版本以后,聚合框架中多了一个新的成员,聚合管道,数据进入管道后就会经过一级级的处理,直到输出。
对于数据量不是特别大,逻辑也不是特别复杂的聚合操作,聚合管道还是比mapReduce有很多优势的:
- 相比mapReduce,聚合管道比较容易理解和使用
- 可以直接使用管道表达式操作符,省掉了很多自定义js function,一定程度上提高执行效率
- 和mapReduce一样,它也可以作用于分片集合
但是,对于数据量大,逻辑复杂的聚合操作,还是要使用mapReduce实现。
聚合管道
在聚合管道中,每一步操作(管道操作符)都是一个工作阶段(stage),所有的stage存放在一个array中。MongoDB文档中的描述如下:
db.collection.aggregate( [ { <stage> }, ... ] )
在聚合管道中,每一个stage都对应一个管道操作符,根据MongoDB文档,聚合管道可以支持以下管道操作符:
$project$project主要用于数据投影,实现字段的重命名、增加和删除。下面例子中,重命名了"name"字段,增加了"birthYear"字段,删除了"_id"字段。 1 > db.runCommand({ 2 ... "aggregate": "school.students", 3 ... "pipeline": [ 4 ... {"$match": {"age": {"$lte": 22}}}, 5 ... {"$project": {"_id": 0, "studentName": "$name", "gender": 1, "birthYear": {"$subtract": [2014, "$age"]}}}, 6 ... {"$sort": {"birthYear":1}} 7 ... ] 8 ... }) 9 { 10 "result" : [ 11 { 12 "gender" : "Female", 13 "studentName" : "Will0", 14 "birthYear" : 1992 15 }, 16 { 17 "gender" : "Male", 18 "studentName" : "Will4", 19 "birthYear" : 1993 20 }, 21 { 22 "gender" : "Male", 23 "studentName" : "Will8", 24 "birthYear" : 1993 25 }, 26 { 27 "gender" : "Female", 28 "studentName" : "Will1", 29 "birthYear" : 1994 30 }, 31 { 32 "gender" : "Male", 33 "studentName" : "Will5", 34 "birthYear" : 1994 35 }, 36 { 37 "gender" : "Female", 38 "studentName" : "Will6", 39 "birthYear" : 1994 40 } 41 ], 42 "ok" : 1 43 } 44 >
$unwind$unwind用来将数组拆分为独立字段。 1 > db.runCommand({ 2 ... "aggregate": "school.students", 3 ... "pipeline": [ 4 ... {"$match": {"age": 23}}, 5 ... {"$project": {"name": 1, "gender": 1, "age": 1, "classes": 1}}, 6 ... {"$unwind": "$classes"} 7 ... ] 8 ... }) 9 { 10 "result" : [ 11 { 12 "_id" : ObjectId("54805220e31c9e1578ed0ccc"), 13 "name" : "Will3", 14 "gender" : "Male", 15 "age" : 23, 16 "classes" : "WPF" 17 }, 18 { 19 "_id" : ObjectId("54805220e31c9e1578ed0ccc"), 20 "name" : "Will3", 21 "gender" : "Male", 22 "age" : 23, 23 "classes" : "C" 24 } 25 ], 26 "ok" : 1 27 } 28 >
$group跟单个的group用法类似,用作分组操作。 使用$group时,必须要指定一个_id域,同时也可以包含一些算术类型的表达式操作符。 下面的例子就是用聚合管道实现得到男生和女生的平均年龄。 1 > db.runCommand({ 2 ... "aggregate": "school.students", 3 ... "pipeline": [ 4 ... {"$group":{"_id":"$gender", "avg": { "$avg": "$age" } }} 5 ... ] 6 ... }) 7 { 8 "result" : [ 9 { 10 "_id" : "Male", 11 "avg" : 21.8 12 }, 13 { 14 "_id" : "Female", 15 "avg" : 22 16 } 17 ], 18 "ok" : 1 19 } 20 >
查询男生和女生的最大年龄 1 > db.runCommand({ 2 ... "aggregate": "school.students", 3 ... "pipeline": [ 4 ... {"$group": {"_id": "$gender", "max": {"$max": "$age"}}} 5 ... ] 6 ... }) 7 { 8 "result" : [ 9 { 10 "_id" : "Male", 11 "max" : 24 12 }, 13 { 14 "_id" : "Female", 15 "max" : 24 16 } 17 ], 18 "ok" : 1 19 } 20 >
管道操作符、管道表达式和表达式操作符上面的例子中,已经接触了这几个概念,下面进行进一步介绍。 管道操作符作为"键",所对应的"值"叫做管道表达式,例如"{"$group": {"_id": "$gender", "max": {"$max": "$age"}}}"
下面列出了常用的表达式操作符,更详细的信息,
总结聚合管道提供了一种mapReduce 的替代方案,mapReduce使用相对来说比较复杂,而聚合管道的拥有固定的接口,一系列可选择的表达式操作符,对于大多数的聚合任务,聚合管道一般来说是首选方法。 Ps: 文章中使用的例子可以通过以下链接查看 http://files.cnblogs.com/wilber2013/pipeline.js
相关推荐
电脑软件热门排行今日推荐热门手游 |