翻译或纠错本页面

邮政编码数据集的聚合

On this page

本章节的例子使用了名为 zipcode 的集合。这个集合位于 media.mongodb.org/zips.json. 可以使用 mongoimport 将这个集合的数据导入到你的 mongod 实例中。

数据模型

Each document in the zipcodes collection has the following form:

{
  "_id": "10280",
  "city": "NEW YORK",
  "state": "NY",
  "pop": 5574,
  "loc": [
    -74.016323,
    40.710537
  ]
}
  • _id 字段保存邮政编码,使用字符串格式。

  • city 字段保存城市名称。一个城市对应多个邮编:不同的区使用不同的邮政编码。

  • state 字段保存州名称的简称(使用了两个字母)。

  • pop 字段保存了人口总数。

  • loc 字段使用经纬度对保存位置信息。

aggregate() Method

所有的例子都是使用 mongoaggregate() 方法。 aggregate() 封装了 aggregate 命令。具体的接口说明可以查看对应你使用的 driver 的文档。

The aggregate() method uses the aggregation pipeline to processes documents into aggregated results. An aggregation pipeline consists of stages with each stage processing the documents as they pass along the pipeline. Documents pass through the stages in sequence.

The aggregate() method in the mongo shell provides a wrapper around the aggregate database command. See the documentation for your driver for a more idiomatic interface for data aggregation operations.

aggregate() 方法会读取集合 zipcodes 中所有的文档。 aggregate() 方法的聚合过程由多个 pipeline 操作符联接而成。

The following aggregation operation returns all states with total population greater than 10 million:

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

$group 操作会读取集合中所有的文档,并为每个州创建一个文档保存输出结果。

  • 新生成的关于州的文档包含了两个字段: _idtotalPoptotalPop 字段保存了使用 $sum 命令对源文档中 pop 字段进行求和的值。

    The new per-state documents have two fields: the _id field and the totalPop field. The _id field contains the value of the state; i.e. the group by field. The totalPop field is a calculated field that contains the total population of each state. To calculate the value, $group uses the $sum operator to add the population field (pop) for each state.

    $match 操作会对输出结果进行过滤,仅保留 totalPop 值大于等于1000万的记录。

    {
      "_id" : "AK",
      "totalPop" : 550043
    }
    
  • The $match stage filters these grouped documents to output only those documents whose totalPop value is greater than or equal to 10 million. The $match stage does not alter the matching documents but outputs the matching documents unmodified.

$match 操作不会对文档做任何修改,它的输出仍然是 $group 输出的文档内容。

SELECT state, SUM(pop) AS totalPop
FROM zipcodes
GROUP BY state
HAVING totalPop >= (10*1000*1000)

参见

$group, $match, $sum

计算所有州的城市人口平均值

The following aggregation operation returns the average populations for cities in each state:

db.zipcodes.aggregate( [
   { $group: { _id: { state: "$state", city: "$city" }, pop: { $sum: "$pop" } } },
   { $group: { _id: "$_id.state", avgCityPop: { $avg: "$pop" } } }
] )

aggregate() 方法会读取集合 zipcodes 中的所有文档。 aggregate() 方法的聚合过程由多个 pipeline 操作符联接而成。

  • $group 操作读取所有的文档,并使用每个源文档的 citystate 字段来创建一个新的文档。

    这个步骤完成后,得到的文档应该是:

    {
      "_id" : {
        "state" : "CO",
        "city" : "EDGEWATER"
      },
      "pop" : 13154
    }
    
  • 第二步的 $group 操作会读取所有文档中的 state 字段的值,并使用 $avg 来计算出 avgCityPop 字段的值。

The documents that result from this aggregation operation resembles the following:

{
  "_id" : "MN",
  "avgCityPop" : 5335
}

参见

$group, $sum, $avg

aggregate() 方法会读取集合 zipcodes 中的所有文档。 aggregate() 方法的聚合过程由多个 pipeline 操作符联接而成。

The following aggregation operation returns the smallest and largest cities by population for each state:

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 操作读取所有的文档,并使用每个源文档的 citystate 字段来创建一个新的文档。

  • 通过设置 _id 字段为一个包含了 statecity 字段的子文档,这样就可以保留 state 字段方便后面的操作使用。这个步骤输出的文档还有一个字段 pop ,它的值是使用 $sum 操作符累加源文档中 pop 字段的值而来。

    完成这步后,输出的文档是这样的:

    {
      "_id" : {
        "state" : "CO",
        "city" : "EDGEWATER"
      },
      "pop" : 13154
    }
    
  • $sort 操作会对文档按 pop 字段值从大到小进行排序,排序操作不会修改文档。

  • 第二步的 $group 操作会根据文档中 _id 内嵌文档的 state 字段值,来对前面的输出文档进行分组。

    $group 操作输出的每个州的文档中包含了4个字段:使用 $last 表达式计算出的 biggestcitybiggestpop 字段,代表了本州中人口最多的城市名和该城市人口总数;使用 $first 表达式计算出的 smallestcitysmallestpop 字段,代表了本州中人口最少的城市名和该城市人口总数;

    The documents, at this stage in the pipeline, resemble the following:

    {
      "_id" : "WA",
      "biggestCity" : "SEATTLE",
      "biggestPop" : 520096,
      "smallestCity" : "BENGE",
      "smallestPop" : 2
    }
    
  • 最后的步骤是 $project,它会把 _id 字段名重新命名为 state ,并把 biggestCity , biggestPop 移动到子文档 biggestCity 中,把 smallestCity , smallestPop 移动到子文档 smallestCity 中。

The output documents of this aggregation operation resemble the following:

{
  "state" : "RI",
  "biggestCity" : {
    "name" : "CRANSTON",
    "pop" : 176404
  },
  "smallestCity" : {
    "name" : "CLAYVILLE",
    "pop" : 45
  }
}
[1]A city can have more than one zip code associated with it as different sections of the city can each have a different zip code.