使用 Zip Code 数据集进行聚合

    在本页面

    本文档中的示例使用zipcodes集合。该系列可在以下网址获得:media.mongodb.org/zips.json。使用mongoimport将此数据集加载到mongod实例中。

    数据模型

    zipcodes集合中的每个文档都具有以下形式:

    1. {
    2. "_id": "10280",
    3. "city": "NEW YORK",
    4. "state": "NY",
    5. "pop": 5574,
    6. "loc": [
    7. -74.016323,
    8. 40.710537
    9. ]
    10. }
    • _id字段将 zip code 保存为 string。
    • city字段包含 city name。一个城市可以有多个与之关联的 zip code,因为城市的不同部分可以各自具有不同的 zip code。
    • state字段包含两个字母 state 缩写。
    • pop字段包含人口。
    • loc字段将位置保存为纬度经度对。

    aggregate()方法

    以下所有示例都使用mongo shell 中的aggregate()帮助程序。

    aggregate()方法使用聚合管道将文档处理为聚合结果。 聚合管道多个阶段组成,每个阶段在文档沿着管道传递时都会对其进行处理。文档按顺序通过各个阶段。

    mongo shell 中的aggregate()方法在聚合数据库命令提供了一个包装器。有关用于数据聚合操作的更惯用的界面,请参阅驱动的文档。

    返回人口超过 1000 万的国家

    以下聚合操作将返回总人口超过 1000 万的所有州:

    1. db.zipcodes.aggregate( [
    2. { $group: { _id: $state“, totalPop: { $sum: $pop } } },
    3. { $match: { totalPop: { $gte: 10*1000*1000 } } }
    4. ] )

    在此 example 中,聚合管道包含$group阶段,后跟$match阶段:

    • 阶段按state字段对zipcode集合的文档进行分组,为每个 state 计算totalPop字段,并为每个唯一的 state 输出文档。

      新的 per-state 文档有两个字段:_id字段和totalPop字段。 _id字段包含state的 value即: group by field。 totalPop字段是一个计算字段,包含每个 state 的总人口。要计算 value,$group使用$sum operator 为每个 state 添加填充字段(pop)。

      $group阶段之后,管道中的文档类似于以下内容:

      1. {
      2. _id : AK“,
      3. totalPop : 550043
      4. }
    • $match阶段过滤这些分组文档,仅输出totalPop value 大于或等于 1000 万的文档。 $match阶段不会更改匹配的文档,但会不加修改地输出匹配的文档。

    此聚合操作的等效SQL是:

    1. SELECT state, SUM(pop) AS totalPop
    2. FROM zipcodes
    3. GROUP BY state
    4. HAVING totalPop >= (10*1000*1000)

    [success] 也可以看看

    $group$match$sum

    按 State 返回平均城市人口

    以下聚合操作返回每个 state 中城市的平均人口数:

    1. db.zipcodes.aggregate( [
    2. { $group: { _id: { state: $state“, city: $city }, pop: { $sum: $pop } } },
    3. { $group: { _id: $_id.state“, avgCityPop: { $avg: $pop } } }
    4. ] )

    在这个 example 中,聚合管道包含$group阶段,后跟另一个$group阶段:

    • 第一个阶段通过citystate的组合对文档进行分组,使用$sum表达式计算每个组合的总体,并为每个citystate组合输出一个文档。 [1]

      在管道中的这个阶段之后,文档类似于以下内容:

      1. {
      2. _id : {
      3. state : CO“,
      4. city : EDGEWATER
      5. },
      6. pop : 13154
      7. }
    • 第二个$group阶段通过_id.state字段(i.e._id文档中的state字段)对管道中的文档进行分组,使用$avg表达式计算每个 state 的平均城市人口(avgCityPop),并为每个 state 输出一个文档。

    此聚合操作产生的文档类似于以下内容:

    1. {
    2. _id : MN“,
    3. avgCityPop : 5335
    4. }

    [success] 也可以看看

    $group$sum$avg

    按 State 返回最大和最小城市

    以下聚合操作按每个 state 的填充返回最小和最大的城市:

    1. db.zipcodes.aggregate( [
    2. {
    3. $group:{
    4. _id: { state: $state“, city: $city },
    5. pop: { $sum: $pop }
    6. }
    7. },
    8. { $sort: { pop: 1 } },
    9. {
    10. $group:{
    11. _id : $_id.state“,
    12. biggestCity: { $last: $_id.city },
    13. biggestPop: { $last: $pop },
    14. smallestCity: { $first: $_id.city },
    15. smallestPop: { $first: $pop }
    16. }
    17. },
    18. // the following $project is optional, and
    19. // modifies the output format.
    20. {
    21. $project:{
    22. _id: 0,
    23. state: $_id“,
    24. biggestCity: { name: $biggestCity“, pop: $biggestPop },
    25. smallestCity: { name: $smallestCity“, pop: $smallestPop }
    26. }
    27. }
    28. ] )

    在此 example 中,聚合管道包含$group阶段,$sort阶段,另一个$group阶段和$project阶段:

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

      在管道的这个阶段,文档类似于以下内容:

      1. {
      2. _id : {
      3. state : CO“,
      4. city : EDGEWATER
      5. },
      6. pop : 13154
      7. }
    • $sort阶段通过pop field value 对管道中的文档进行排序,从最小到最大; 即:通过增加 order。此操作不会更改文档。

    • 下一个$group阶段按_id.state字段(即:_id文档中的state字段)对 now-sorted 文档进行分组,并为每个 state 输出一个文档。

      该阶段还为每个 state 计算以下四个字段。使用$last表达式,$group operator 创建biggestCitybiggestPop字段,用于存储人口和人口最多的城市。使用$first表达式,$group operator 创建smallestCitysmallestPop字段,用于存储人口和人口最少的城市。

      在管道的这个阶段,文件类似于以下内容:

      1. {
      2. _id : WA“,
      3. biggestCity : SEATTLE“,
      4. biggestPop : 520096,
      5. smallestCity : BENGE“,
      6. smallestPop : 2
      7. }
    • 最后的$project阶段将_id字段重命名为state,并将biggestCitybiggestPopsmallestCitysmallestPop移动到biggestCitysmallestCity嵌入文档中。

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

    1. {
    2. state : RI“,
    3. biggestCity : {
    4. name : CRANSTON“,
    5. pop : 176404
    6. },
    7. smallestCity : {
    8. name : CLAYVILLE“,
    9. pop : 45
    10. }
    11. }

    [1] 一个城市可以有多个与之关联的 zip code,因为城市的不同部分可以各自具有不同的 zip code。

    译者:李冠飞

    校对:李冠飞

    参见

    原文 - Example with ZIP Code Data