$bucket(集計)
定義
Considerations
$bucket
およびメモリ制限
$bucket
ステージには100メガバイトの RAM 制限があります。 デフォルトでは、 ステージがこの制限を超えると、 $bucket
はエラーを返します。 ステージ処理に使用できるスペースを増やすには、 allowDiskUseオプションを使用して集計パイプライン ステージで一時ファイルにデータを書込みます。
構文
{ $bucket: { groupBy: <expression>, boundaries: [ <lowerbound1>, <lowerbound2>, ... ], default: <literal>, output: { <output1>: { <$accumulator expression> }, ... <outputN>: { <$accumulator expression> } } } }
$bucket
ドキュメントには次のフィールドが含まれています。
フィールド | タイプ | 説明 | |||
---|---|---|---|---|---|
式 | ドキュメントをグループ化するための式。フィールドパスを指定するには、フィールド名の前にドル記号(
| ||||
配列 | |||||
literal | |||||
ドキュメント | 省略可能。
|
動作
$bucket
では以下の条件の 1 つ以上が満たされる必要があります。そうでない場合、操作でエラーがスローされます。
groupBy
式が配列またはドキュメントに変換される場合、$bucket
は $sort
の比較ロジックを使用して入力ドキュメントをバケットに配置します。
例
年別バケットと バケット結果に基づくフィルタリング
mongosh
では、次のドキュメントを含むartists
という名前のサンプル コレクションが作成されます。
db.artists.insertMany([ { "_id" : 1, "last_name" : "Bernard", "first_name" : "Emil", "year_born" : 1868, "year_died" : 1941, "nationality" : "France" }, { "_id" : 2, "last_name" : "Rippl-Ronai", "first_name" : "Joszef", "year_born" : 1861, "year_died" : 1927, "nationality" : "Hungary" }, { "_id" : 3, "last_name" : "Ostroumova", "first_name" : "Anna", "year_born" : 1871, "year_died" : 1955, "nationality" : "Russia" }, { "_id" : 4, "last_name" : "Van Gogh", "first_name" : "Vincent", "year_born" : 1853, "year_died" : 1890, "nationality" : "Holland" }, { "_id" : 5, "last_name" : "Maurer", "first_name" : "Alfred", "year_born" : 1868, "year_died" : 1932, "nationality" : "USA" }, { "_id" : 6, "last_name" : "Munch", "first_name" : "Edvard", "year_born" : 1863, "year_died" : 1944, "nationality" : "Norway" }, { "_id" : 7, "last_name" : "Redon", "first_name" : "Odilon", "year_born" : 1840, "year_died" : 1916, "nationality" : "France" }, { "_id" : 8, "last_name" : "Diriks", "first_name" : "Edvard", "year_born" : 1855, "year_died" : 1930, "nationality" : "Norway" } ])
次の操作では、year_born
フィールドに従ってドキュメントをバケットにグループ化し、バケット内のドキュメント数に基づいてフィルタリングします。
db.artists.aggregate( [ // First Stage { $bucket: { groupBy: "$year_born", // Field to group by boundaries: [ 1840, 1850, 1860, 1870, 1880 ], // Boundaries for the buckets default: "Other", // Bucket ID for documents which do not fall into a bucket output: { // Output for each bucket "count": { $sum: 1 }, "artists" : { $push: { "name": { $concat: [ "$first_name", " ", "$last_name"] }, "year_born": "$year_born" } } } } }, // Second Stage { $match: { count: {$gt: 3} } } ] )
- 第 1 ステージ
$bucket
ステージでは、ドキュメントはyear_born
フィールドでバケットにグループ化されます。 バケットには次の境界があります。[1840, 1850) は下限
1840
を包含し、上限1850
を除外します。[1850, 1860) は、下限
1850
を包含し、上限1860
を除外します。[1860, 1870) は、下限
1860
を包含し、上限1870
を除外します。[1870, 1880) は、下限
1870
を包含し、上限1880
を除外します。ドキュメントに
year_born
フィールドが含まれていない場合、またはそのyear_born
フィールドが上記の範囲外の場合、そのドキュメントは_id
値"Other"
を持つデフォルトのバケットに配置されます。
このステージには、返すフィールドを決定するための出力ドキュメントが含まれます。
フィールド説明_id
バケットの下限を含みます。count
バケット内のドキュメント数。artists
バケット内の各アーティストに関する情報が記載されているドキュメントの配列。各ドキュメントにはアーティストに関する次の情報が記載されています。
name
は、アーティストのfirst_name
とlast_name
の連結($concat
)を含みます。year_born
このステージでは、次のドキュメントを次のステージに渡します。
{ "_id" : 1840, "count" : 1, "artists" : [ { "name" : "Odilon Redon", "year_born" : 1840 } ] } { "_id" : 1850, "count" : 2, "artists" : [ { "name" : "Vincent Van Gogh", "year_born" : 1853 }, { "name" : "Edvard Diriks", "year_born" : 1855 } ] } { "_id" : 1860, "count" : 4, "artists" : [ { "name" : "Emil Bernard", "year_born" : 1868 }, { "name" : "Joszef Rippl-Ronai", "year_born" : 1861 }, { "name" : "Alfred Maurer", "year_born" : 1868 }, { "name" : "Edvard Munch", "year_born" : 1863 } ] } { "_id" : 1870, "count" : 1, "artists" : [ { "name" : "Anna Ostroumova", "year_born" : 1871 } ] } - 第 2 ステージ
$match
ステージでは、前のステージからの出力をフィルタリングして、3 つ以上のドキュメントを含むバケットのみが返されます。この操作を実行すると次のドキュメントが返されます。
{ "_id" : 1860, "count" : 4, "artists" : [ { "name" : "Emil Bernard", "year_born" : 1868 }, { "name" : "Joszef Rippl-Ronai", "year_born" : 1861 }, { "name" : "Alfred Maurer", "year_born" : 1868 }, { "name" : "Edvard Munch", "year_born" : 1863 } ] }
$facet と $bucket の併用による複数フィールドのバケット化
$facet
ステージを使用して、1 つのステージで複数の$bucket
集計を実行できます。
mongosh
では、次のドキュメントを含むartwork
という名前のサンプル コレクションが作成されます。
db.artwork.insertMany([ { "_id" : 1, "title" : "The Pillars of Society", "artist" : "Grosz", "year" : 1926, "price" : NumberDecimal("199.99") }, { "_id" : 2, "title" : "Melancholy III", "artist" : "Munch", "year" : 1902, "price" : NumberDecimal("280.00") }, { "_id" : 3, "title" : "Dancer", "artist" : "Miro", "year" : 1925, "price" : NumberDecimal("76.04") }, { "_id" : 4, "title" : "The Great Wave off Kanagawa", "artist" : "Hokusai", "price" : NumberDecimal("167.30") }, { "_id" : 5, "title" : "The Persistence of Memory", "artist" : "Dali", "year" : 1931, "price" : NumberDecimal("483.00") }, { "_id" : 6, "title" : "Composition VII", "artist" : "Kandinsky", "year" : 1913, "price" : NumberDecimal("385.00") }, { "_id" : 7, "title" : "The Scream", "artist" : "Munch", "year" : 1893 /* No price*/ }, { "_id" : 8, "title" : "Blue Flower", "artist" : "O'Keefe", "year" : 1918, "price" : NumberDecimal("118.42") } ])
次の操作では、$facet
ステージ内の 2 つの $bucket
ステージを使用して 2 つのグループが作成されます。1 つは price
別のグループ、もう 1 つは year
別のグループです。
db.artwork.aggregate( [ { $facet: { // Top-level $facet stage "price": [ // Output field 1 { $bucket: { groupBy: "$price", // Field to group by boundaries: [ 0, 200, 400 ], // Boundaries for the buckets default: "Other", // Bucket ID for documents which do not fall into a bucket output: { // Output for each bucket "count": { $sum: 1 }, "artwork" : { $push: { "title": "$title", "price": "$price" } }, "averagePrice": { $avg: "$price" } } } } ], "year": [ // Output field 2 { $bucket: { groupBy: "$year", // Field to group by boundaries: [ 1890, 1910, 1920, 1940 ], // Boundaries for the buckets default: "Unknown", // Bucket ID for documents which do not fall into a bucket output: { // Output for each bucket "count": { $sum: 1 }, "artwork": { $push: { "title": "$title", "year": "$year" } } } } } ] } } ] )
- 最初のファセット
最初のファセットは、入力ドキュメントを
price
でグループ化します。バケットには次の境界があります。[0, 200) は下限
0
を包含し、上限200
を除外します。[200, 400) は下限
200
を包含し、上限400
を除外します。「その他」は
default
バケットで、価格がないか、上記の範囲外の価格のドキュメントを含みます。
$bucket
ステージには、返されるフィールドを決定するための出力ドキュメントが含まれます。フィールド説明_id
バケットの下限を含みます。count
バケット内のドキュメント数。artwork
バケット内の各アート作品に関する情報を含むドキュメントの配列。averagePrice
$avg
演算子を使用して、バケット内のすべてのアート作品の平均価格を表示します。- 2 番目のファセット
2 番目のファセットでは、入力ドキュメントを
year
でグループ化します。バケットには次の境界があります。[1890、1910) は、下限
1890
を包含し、上限1910
を除外します。[1910, 1920) は、下限
1910
を包含し、上限1920
を除外します。[1920, 1940) は、下限
1910
を包含し、上限1940
を除外します。「不明」は
default
バケットで、年数がないか、上記の範囲外の年数であるドキュメントを含みます。
$bucket
ステージには、返されるフィールドを決定するための出力ドキュメントが含まれます。フィールド説明count
バケット内のドキュメント数。artwork
バケット内の各アート作品に関する情報を含むドキュメントの配列。- 出力
この操作を実行すると次のドキュメントが返されます。
{ "price" : [ // Output of first facet { "_id" : 0, "count" : 4, "artwork" : [ { "title" : "The Pillars of Society", "price" : NumberDecimal("199.99") }, { "title" : "Dancer", "price" : NumberDecimal("76.04") }, { "title" : "The Great Wave off Kanagawa", "price" : NumberDecimal("167.30") }, { "title" : "Blue Flower", "price" : NumberDecimal("118.42") } ], "averagePrice" : NumberDecimal("140.4375") }, { "_id" : 200, "count" : 2, "artwork" : [ { "title" : "Melancholy III", "price" : NumberDecimal("280.00") }, { "title" : "Composition VII", "price" : NumberDecimal("385.00") } ], "averagePrice" : NumberDecimal("332.50") }, { // Includes documents without prices and prices greater than 400 "_id" : "Other", "count" : 2, "artwork" : [ { "title" : "The Persistence of Memory", "price" : NumberDecimal("483.00") }, { "title" : "The Scream" } ], "averagePrice" : NumberDecimal("483.00") } ], "year" : [ // Output of second facet { "_id" : 1890, "count" : 2, "artwork" : [ { "title" : "Melancholy III", "year" : 1902 }, { "title" : "The Scream", "year" : 1893 } ] }, { "_id" : 1910, "count" : 2, "artwork" : [ { "title" : "Composition VII", "year" : 1913 }, { "title" : "Blue Flower", "year" : 1918 } ] }, { "_id" : 1920, "count" : 3, "artwork" : [ { "title" : "The Pillars of Society", "year" : 1926 }, { "title" : "Dancer", "year" : 1925 }, { "title" : "The Persistence of Memory", "year" : 1931 } ] }, { // Includes documents without a year "_id" : "Unknown", "count" : 1, "artwork" : [ { "title" : "The Great Wave off Kanagawa" } ] } ] }