导入数据
为了方便我们的练习节省时间,最好的方法就是使用官方提供的数据。
数据地址:传送门
先下载下来,然后通过以下方法导入数据
1 | mongoimport --db=zipcodes --collection=zipcodes --file=zips.json |
没个 item 字段:
1 | { |
2 | "_id": "10280", |
3 | "city": "NEW YORK", |
4 | "state": "NY", |
5 | "pop": 5574, |
6 | "loc": [-74.016323, 40.710537] |
7 | } |
- _id 表示邮政编码
- city 表示城市名称
- state 表示城市所属州
- pop 表示人口
- loc 表示所在地的精度和维度
查询州人口大于 1000 万
1 | db.zipcodes.aggregate([ |
2 | { $group: { _id: "$state", totalPop: { $sum: "$pop" } } }, |
3 | { $match: { totalPop: { $gte: 10 * 1000 * 1000 } } } |
4 | ]); |
聚合管道会至上而下的将处理结果传递给下一个阶段处理。上面例子就是先将文档进行以 state
为单位进行分组处理,计算每个州的人口总和,将分组后的统计记过通过聚合管道传递给下一个$match 进行筛选处理。
查询州下城市的平均人口
1 | db.zipcodes.aggregate([ |
2 | { |
3 | $group: { _id: { state: "$state", city: "$city" }, pop: { $sum: "$pop" } } |
4 | }, |
5 | { $group: { _id: "$_id.state", avgCityPop: { $avg: "$pop" } } } |
6 | ]); |
解释下:这里我们先按照州和城市进行分组并计算人口总数,在将统计的结果,通过管道传递给下一个处理条件。
- 分解开来理解就是,第一次分组后的单条数据结果为:
1 | // { $group: { _id: { state: "$state", city: "$city" }, pop: { $sum: "$pop" } } }, |
2 | [{ |
3 | "_id" : { |
4 | "state" : "CO", |
5 | "city" : "EDGEWATER" |
6 | }, |
7 | "pop" : 13154 |
8 | },...] |
- 在这个数据结果的基础上,我们在进行分组聚合
1 | // 以这个条件 { $group: { _id: "$_id.state", avgCityPop: { $avg: "$pop" } } } |
2 | [{ |
3 | "_id" : "MN", |
4 | "avgCityPop" : 5335 |
5 | }, ...] |
可以看出来,我们的查询结果是按照传入数组至上而下的进行管道式处理。
查询一个州中最大和最小城市人口数据
有了上面两个案例的思路,我们可以借鉴的思路就是:
- 先把数据按州、城市进行分组,并计算人口和
- 对分组后的数据进行排序
- 再讲分组信息按州进行分组,找出人口最大城市和人口最小城市
1 | db.zipcodes.aggregate([ |
2 | { |
3 | $group: { |
4 | _id: { state: "$state", city: "$city" }, |
5 | pop: { sum: "$pop" } |
6 | } |
7 | }, |
8 | { $sort: { pop: 1 } }, // 1升序,-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 | |
19 | // 自定义返回字段,相当于我们MySQL中的 select |
20 | { |
21 | $project: { |
22 | _id: 0, // 隐藏默认_id |
23 | state: "$_id", |
24 | biggestCity: { name: "$biggestCity", pop: "$biggestPop" }, |
25 | smallestCity: { name: "$smallestCity", pop: "$smallestPop" } |
26 | } |
27 | } |
28 | ]); |
只要理解聚合管道,我们就可以逐步的对数据记性逐级处理,来获取我们想要的数据