英文原文地址:https://docs.mongodb.com/v3.2/tutorial/aggregation-zip-code-data-set/。
本文章属个人翻译,作个人学习之用,如有雷同,纯属巧合。如有错误之处,欢迎指正。
对邮编数据集进行聚集
该篇文章的例子使用zipcodes
集合。该集合在media.mongodb.org/zips.json可以找到,使用mongoimport
来把该数据集导入到mongod
实例中。
数据模型
zipcodes
集合中的每个文档有如下格式:
{
"_id": "10280",
"city": "NEW YORK",
"state": "NY",
"pop": 5574,
"loc": [
-74.016323,
40.710537
]
}
- _id字段保存的是邮政编码,字符串。
- city字段保存的是城市名。一个城市可以有多个邮编与之管理,因为该城市的不同区可以有不同的邮编。
- state字段保存的是两字母缩写的州名。
- pop字段保存的是人口。
- loc字段保存的是以经纬对形式的位置。
aggregate()方法
下面的所有例子都是在mongo
shell中使用aggregate()
帮助方法。
aggregate()
方法使用聚集管道来处理文档车功能聚集结果。一个聚集管道由多个阶段组成,每个阶段处理通过管道的文档。文档按顺序依次通过各个阶段。
mongo
shell中的aggregate()
方法提供了对数据库命令aggregate
的一个封装。
返回人口超过1000万的州
下面的聚集操作返回总人口超过1000万的所有州:
db.zipcodes.aggregate( [
{ $group: { _id: "$state", totalPop: { $sum: "$pop" } } },
{ $match: { totalPop: { $gte: 10*1000*1000 } } }
] )
这个例子中,聚集管道由$group
阶段,以及后面的$match
阶段组成:
$group
阶段通过state
字段对zipcode
集合中的文档进行分组,对每个州计算totalPop
字段,然后对每个唯一的州输出一个文档。新的每个州的文档有两个字段,_id字段和totalPop字段。_id字段包含州state的值,即分组的字段。totalPop是一个计算字段,包含了每个州的总人口。
$group
使用$sum
操作符来对每个州的人口相加来计算这个字段。$group
阶段后,管道中的文档类似如下:{ "_id" : "AK", "totalPop" : 550043 }
$match
阶段对这些分组的文档进行过滤,只输出totalPop大于或等于1000万的文档。$match
阶段并不修改匹配的文档,只是不经修改地输出匹配的文档。
该聚集操作的等价SQL语句如下:
SELECT state, SUM(pop) AS totalPop
FROM zipcodes
GROUP BY state
HAVING totalPop >= (10*1000*1000)
按州返回平均城市人口
下面的聚集操作返回每个州的平均城市人口:
db.zipcodes.aggregate( [
{ $group: { _id: { state: "$state", city: "$city" }, pop: { $sum: "$pop" } } },
{ $group: { _id: "$_id.state", avgCityPop: { $avg: "$pop" } } }
] )
该例子中,聚集管道由两个$group
组成:
第一个
$group
阶段通过city和state的组合来分组文档,并使用$sum
表达式来计算每个组合的人口总数,然后对每个city和state的组合输出一个文档。该阶段之后,文档类似如下:{ "_id" : { "state" : "CO", "city" : "EDGEWATER" }, "pop" : 13154 }
第二个
$group
阶段通过_id.state
字段来分组文档(即_id文档中的state字段),使用$avg
表达式对每个州计算平均城市人口(avgCityPop),然后对每个州输出一个文档。
这次聚集操作的结果,文档类似如下:
{
"_id" : "MN",
"avgCityPop" : 5335
}
按州返回最大和最小的城市
下面的聚集操作按人口返回每个州的最大和最小城市:
db.zipcodes.aggregate( [
{ $group:
{
_id: { state: "$state", city: "$city" },
pop: { $sum: "$pop" }
}
},
{ $sort: { pop: 1 } },
{ $group:
{
_id : "$_id.state",
biggestCity: { $last: "$_id.city" },
biggestPop: { $last: "$pop" },
smallestCity: { $first: "$_id.city" },
smallestPop: { $first: "$pop" }
}
},
// the following $project is optional, and
// modifies the output format.
{ $project:
{ _id: 0,
state: "$_id",
biggestCity: { name: "$biggestCity", pop: "$biggestPop" },
smallestCity: { name: "$smallestCity", pop: "$smallestPop" }
}
}
] )
该例子中,聚集管道由一个$group
阶段,一个$sort
阶段,另一个$group
阶段,和一个$project
阶段组成。
第一个
$group
阶段按city和state的组合来分组文档,对每个组合计算pop值的和,然后对每个city和state的组合输出一个文档。该阶段之后,文档类似如下:
{ "_id" : { "state" : "CO", "city" : "EDGEWATER" }, "pop" : 13154 }
$sort
阶段在管道中按pop字段的值duii文档排序,从最小到最大(即升序)。该操作不会修改文档。下一个
$group
阶段按_id.state
字段(即_id文档中的state字段)对已经有序的文档分组,对每个州输出一个文档。该阶段也对每个州计算四个字段。使用
$last
表达式,$group
操作符创建了保存最大人口的城市和最大人口的biggeestCity和biggestPop字段。使用$first
表达式,$group
操作符欻功能键了保存最小人口的城市和最小人口的smallestCity和smallestPop字段。该阶段后的文档类似如下:
{ "_id" : "WA", "biggestCity" : "SEATTLE", "biggestPop" : 520096, "smallestCity" : "BENGE", "smallestPop" : 2 }
最后的
$project
阶段把_id字段重命名为state,并把biggestCity、biggestPop、smallestCity和smallestPop移到biggestCity和smallestCity嵌入文档中。
该聚集操作的输出文档类似如下:
{
"state" : "RI",
"biggestCity" : {
"name" : "CRANSTON",
"pop" : 176404
},
"smallestCity" : {
"name" : "CLAYVILLE",
"pop" : 45
}
}