Docs 菜单

Docs 主页开发应用程序MongoDB Manual

与邮政编码数据集的聚合

在此页面上

  • 数据模型
  • aggregate() 方法
  • 返回人口超过 1,000 万的州
  • 返回各州的平均城市人口
  • 按省/市/自治区返回最大城市和最小城市

本文档中的示例使用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 字段会以经纬度对的形式保存位置。

以下所有示例都使用 mongosh 中的aggregate()助手

aggregate() 方法使用聚合管道将文档处理为聚合结果。一个聚合管道由多个阶段组成,其中每个阶段均会处理沿管道传递的文档。文档会按顺序通过各个阶段。

aggregate()中的 方法对mongosh aggregate数据库命令进行封装。请参阅 驱动程序 文档,了解更惯用的数据聚合操作接口。

以下聚合操作返回总人口大于 1,000 万的所有州:

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 值大于或等于 1,000 万的文档。$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 阶段按 citystate 的组合对文档进行分组,使用 $sum 表达式计算每个组合的总量,并为每个 citystate 组合输出一个文档。[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" }
}
}
] )

在此示例中,aggregation pipeline 由一个 $group 阶段、一个 $sort 阶段、另一个 $group 阶段和一个 $project 阶段组成:

  • 第一个 $group 阶段按 citystate 的组合对文档进行分组,计算每个组合的 pop 值的 sum,并为每个 citystate 组合输出一个文档。

    在此管道阶段,文档如下所示:

    {
    "_id" : {
    "state" : "CO",
    "city" : "EDGEWATER"
    },
    "pop" : 13154
    }
  • $sort 阶段按照 pop 字段值从小到大排列管道中的文档,即递增顺序。此操作不会更改文档。

  • 接下来的 $group 阶段会按 _id.state 字段(即 _id 文档中的 state 字段)对现已排序的文档分组,并输出每个状态的对应文档。

    此阶段还会为每个状态计算以下四个字段。$group 操作符使用 $last 表达式,创建 biggestCitybiggestPop 字段,分别存储人口最多的城市和具体人口数。$group 操作符使用 $first 表达式,创建 smallestCitysmallestPop 字段,分别存储人口最少的城市和具体人口数。

    在这个管道阶段,文档如下所示:

    {
    "_id" : "WA",
    "biggestCity" : "SEATTLE",
    "biggestPop" : 520096,
    "smallestCity" : "BENGE",
    "smallestPop" : 2
    }
  • 最后的 $project 阶段将 _id 字段重命名为 state,并将 biggestCitybiggestPopsmallestCitysmallestPop 移至 biggestCitysmallestCity 嵌入式文档中。

此聚合操作的输出文档应类似如下内容:

{
"state" : "RI",
"biggestCity" : {
"name" : "CRANSTON",
"pop" : 176404
},
"smallestCity" : {
"name" : "CLAYVILLE",
"pop" : 45
}
}
[1] 一个城市可有多个与其关联的邮政编码,因为该城市的不同区域可能有不同的邮政编码。
← 聚合管道和分片集合