このドキュメントの例では、 zipcodesコレクションを使用します。このコレクションはメディア.mongodb.org/zips.jsonで入手できます。mongoimport を使用して、このデータセットを mongod インスタンスに読み込みます。
データモデル
zipcodes コレクション内の各ドキュメントの形式は次のとおりです。
{ "_id": "10280", "city": "NEW YORK", "state": "NY", "pop": 5574, "loc": [ -74.016323, 40.710537 ] }
_idフィールドには、郵便番号が文字列として保持されます。cityフィールドには、都市名が保持されます。1 つの都市に複数の郵便番号を関連付けることができます。これは、都市の区画ごとに異なる郵便番号が付けられている場合があるためです。stateフィールドには 2 文字の州の略称が保持されます。popフィールドには人口が保持されます。locフィールドには、ロケーションが経度と緯度のペアで保持されます。
aggregate() 方式
以下のすべての例では、aggregate() で mongosh のヘルパーを使用しています。
aggregate() メソッドは、集約パイプラインを使用してドキュメントを集約された結果に処理します。集約パイプラインはステージで構成され、各ステージではパイプラインを通過してドキュメントを処理します。ドキュメントは、ステージを順番に通過します。
mongoshのaggregate()メソッドは、aggregate データベースコマンドを囲むラッパーを提供します。データ集計操作のより慣用的なインターフェイスについては、ドライバーのドキュメントを参照してください。
人口が1,000万人を超える州を返す
次の集計操作では、総人口が 1,000 万人を超えるすべての州を返します。
db.zipcodes.aggregate( [ { $group: { _id: "$state", totalPop: { $sum: "$pop" } } }, { $match: { totalPop: { $gte: 10*1000*1000 } } } ] )
この例では、集計パイプラインは、$group ステージとそれに続く $match ステージで構成されています。
$groupステージでは、zipcodeコレクションのドキュメントをstateフィールドごとにグループ化し、各州のtotalPopフィールドを計算して、一意の州ごとにドキュメントを出力します。新しい州ごとのドキュメントには、
_idフィールドとtotalPopフィールドの 2 つのフィールドがあります。_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ステージでは、ドキュメントをcityとstateの組み合わせでグループ化し、$sum式を使用して各組み合わせの人口を計算し、cityとstateの組み合わせごとにドキュメントを出力します。[1]パイプラインのこのステージの後、ドキュメントは次のようになります。
{ "_id" : { "state" : "CO", "city" : "EDGEWATER" }, "pop" : 13154 } 2 番目の
$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の値のsumを計算し、cityとstateの組み合わせごとにドキュメントを出力します。パイプラインのこのステージでは、ドキュメントは次のようになります。
{ "_id" : { "state" : "CO", "city" : "EDGEWATER" }, "pop" : 13154 } $sortステージでは、popフィールドの値でパイプライン内のドキュメントを小さいものから大きいものへ、つまり昇順で並べます。この操作では、ドキュメントは変更されません。次の
$groupステージでは、ソートされたドキュメントを_id.stateフィールド(つまり、_idドキュメント内のstateフィールド)でグループ化し、各州のドキュメントを出力します。このステージでは、各州について次の 4 つのフィールドも計算されます。
$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] | 1 つの都市に複数の郵便番号を関連付けることができます。これは、都市の区画ごとに異なる郵便番号が付けられている場合があるためです。 |