MongoDB数据库学习-聚集-对邮编数据集进行聚集。
对邮编数据集进行聚集
该篇文章的例子使用zipcodes集合。该集合在media.mongodb.org/zips.json可以找到,使用mongoimport来把该数据集导入到mongod实例中。
数据模型
zipcodes集合中的每个文档有如下格式:
_id字段保存的是邮政编码,字符串。 city字段保存的是城市名。一个城市可以有多个邮编与之管理,因为该城市的不同区可以有不同的邮编。 state字段保存的是两字母缩写的州名。 pop字段保存的是人口。 loc字段保存的是以经纬对形式的位置。{
"_id": "10280", "city": "NEW YORK", "state": "NY", "pop": 5574, "loc": [ -74.016323, 40.710537 ]}
aggregate()方法
下面的所有例子都是在mongoshell中使用aggregate()帮助方法。
aggregate()方法使用聚集管道来处理文档车功能聚集结果。一个聚集管道由多个阶段组成,每个阶段处理通过管道的文档。文档按顺序依次通过各个阶段。
mongoshell中的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 totalPopFROM zipcodesGROUP BY stateHAVING 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),然后对每个州输出一个文档。
这次聚集操作的结果,文档类似如下:
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 }
}