使用邮编数据集进行聚合
本文件中的示例使用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()
方法
以下所有示例都使用了 aggregate()
辅助函数在 mongosh
中。
aggregate()
方法使用 聚合管道 来处理文档并生成聚合结果。一个 聚合管道 由 阶段 组成,每个阶段在管道中处理文档。文档按顺序通过阶段。
aggregate()
方法在 mongosh
中提供了一个数据库命令 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
操作符将每个州的人口字段(pop)相加。在
$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
阶段
第一个
$group
阶段根据 city 和 state 的组合分组文档,使用$sum
表达式计算每个组合的人口,并为每个 city 和 state 组合输出一个文档。[1]在管道中的此阶段之后,文档类似于以下内容
{ "_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
字段值对管道中的文档进行排序,从小到大;即按升序排序。此操作不会更改文档。下一个
$group
阶段根据_id.state
字段(即_id
文档内的state
字段)对现在已排序的文档进行分组,并为每个州输出一个文档。该阶段还为每个状态计算以下四个字段。使用
$last
表达式,$group
操作符创建了biggestCity
和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 } }
[1] | 一个城市可以与多个邮政编码相关联,因为城市的不同部分可以各自有不同的邮政编码。 |