Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

$group(集計ステージ)

$group

$group ステージは、グループ キーに従って、同じフィールドまたは式を持つ複数のドキュメントを単一のドキュメントに結合します。その結果、一意のグループ キーごとに 1 つのドキュメントが生成されます。

グループキーは、多くの場合、フィールドまたはフィールドのグループです。グループキーは、式の結果にすることもできます。グループキーを設定するには、$groupパイプライン ステージの_idフィールドを使用します。使用例については以下を参照してください。

$group ステージの出力では、 _id フィールドにそのドキュメントのグループ キーが設定されます。

出力ドキュメントには、アキュムレータ式 を使用して設定された追加のフィールドを含めることもできます。

注意

$groupは出力ドキュメントを順序付けしません

次の環境でホストされる配置には $group を使用できます。

  • MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです

  • MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン

  • MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン

$groupステージのプロトタイプ形式は次のとおりです。

{
$group:
{
_id: <expression>, // Group key
<field1>: { <accumulator1> : <expression1> },
...
}
}
フィールド
説明

_id

必須。_id式はグループキーを指定します。 null の _id 値またはその他の定数値を指定すると、$group ステージはすべての入力ドキュメントにわたる値を集計する単一のドキュメントを返します。 「 Null によるグループの例 」を参照してください。

field

_id演算子とアキュムレータ 演算子は、有効な任意のexpressionを受け入れることができます。 式の詳細については、「式 」を参照してください。

$group はブロッキング ステージであり、パイプラインはデータを処理する前にすべての入力データが検索されるまで待機します。ブロッキング ステージは、複数のステージを持つパイプラインの並列処理を減らすため、パフォーマンスを低下させる可能性があります。ブロッキング ステージでは、大規模なデータセットに対して大量のメモリが使用される場合もあります。

<accumulator> 演算子は、次のアキュムレータ 演算子のいずれかである必要があります。

名前
説明

ユーザー定義のアキュムレータ関数の結果を返します。

グループごとのユニークな式値の配列を返します。配列要素の順序は未定義です。

バージョン 5.0 で変更$setWindowFieldsステージで使用可能です。

数値の平均を返します。数値以外の値は無視されます。

バージョン 5.0 で変更$setWindowFieldsステージで使用可能です。

指定ソート順に従って、グループ内の最下位の要素を返します。

バージョン 5.2 で追加

$groupおよび$setWindowFieldsステージで利用可能です。

グループ内の下位 n フィールドの集計を、指定のソート順序に従って返します。

バージョン 5.2 で追加

$groupおよび$setWindowFieldsステージで利用可能です。

グループにあるドキュメントの数を返します。

$count パイプライン ステージとは異なります。

バージョン 5.0 で追加され、$groupおよび$setWindowFieldsステージで利用できます。

グループ内の最初のドキュメントのの結果を返します。

バージョン 5.0 で変更$setWindowFieldsステージで使用可能です。

グループ内の最初の n 個の要素の集計を返します。ドキュメントが定義どおりの順序になっている場合にのみ意味があります。$firstN 配列演算子とは異なります。

バージョン 5.2 で追加され$group$setWindowFieldsステージで使用できます。

グループ内の最後のドキュメントのの結果を返します。

バージョン 5.0 で変更$setWindowFieldsステージで使用可能です。

グループ内の最後の n 要素の集計を返します。ドキュメントが定義どおりの順序になっている場合にのみ意味があります。$lastN 配列演算子とは異なります。

バージョン 5.2 で追加され$group$setWindowFieldsステージで使用できます。

グループごとの最大の式の値を返します。

バージョン 5.0 で変更$setWindowFieldsステージで使用可能です。

グループ内の最大値を持つ n 要素の集計を返します。$maxN 配列演算子とは異なります。

バージョン 5.2 で追加

$group$setWindowFields 、および式 として使用できます。

中央値、つまり 50 パーセンタイルの近似値がスカラー値として返されます。

バージョン 7.0 で追加

この演算子は、次に示すステージでアキュムレータとして使用できます。

集計式としても使用できます。

各グループの入力ドキュメントを組み合わせて作成したドキュメントを返します。

グループごとの最小の式値を返します。

バージョン 5.0 で変更$setWindowFieldsステージで使用可能です。

グループ内の n 個の最小値要素の集合を返します。$minN配列演算子とは異なります。

バージョン 5.2 で追加

$group$setWindowFields 、および式 として使用できます。

指定パーセンタイル値に対応するスカラー値の配列を返します。

バージョン 7.0 で追加

この演算子は、次に示すステージでアキュムレータとして使用できます。

集計式としても使用できます。

グループごとのドキュメントの式値の配列を返します。

バージョン 5.0 で変更$setWindowFieldsステージで使用可能です。

入力値の母集団標準偏差を返します。

バージョン 5.0 で変更$setWindowFieldsステージで使用可能です。

入力値のサンプル標準偏差を返します。

バージョン 5.0 で変更$setWindowFieldsステージで使用可能です。

数値の合計を返します。数値以外の値は無視されます。

バージョン 5.0 で変更$setWindowFieldsステージで使用可能です。

指定ソート順に従って、グループ内の最上位の要素を返します。

バージョン 5.2 で追加

$groupおよび$setWindowFieldsステージで利用可能です。

グループ内の上位 n フィールドの集計を、指定のソート順序に従って返します。

バージョン 5.2 で追加

$groupおよび$setWindowFieldsステージで利用可能です。

$groupステージが100メガバイトの RAM を超える場合、MongoDB は一時ファイルにデータを書込みます。 ただし、 allowDiskUseオプションがfalseに設定されている場合、 $groupはエラーを返します。 詳細については、「集計パイプラインの制限 」を参照してください。

このセクションでは、 $groupのパフォーマンスを向上させるための最適化について説明します。 手動で行うことができる最適化と、MongoDB が内部で行う最適化があります。

パイプラインsortsgroupsが同じフィールドで実行され、 $groupステージで$firstまたは$lastアキュムレータ 演算子のみが使用される場合は、並べ替え順序に一致するグループ化されたフィールドにインデックスを追加することを検討してください。場合によっては、$group ステージでインデックスを使用して各グループの最初または最後のドキュメントをすばやく見つけることができます。

moviesコレクションにインデックス{ year: 1, title: 1 } が含まれている場合、次のパイプラインはそのインデックスを使用して各グループの最初のドキュメントを検索できます。

db.movies.aggregate([
{
$sort: { year: 1, title: 1 }
},
{
$group: {
_id: { year: "$year" },
title: { $first: "$title" }
}
}
])

バージョン 5.2 以降、MongoDB は、次のいずれかの場合にスロットベースの実行クエリ エンジンを使用して$groupステージを実行します。

  • $group はパイプラインの第一ステージです。

  • パイプラインの先行ステージもすべて、スロットベースの実行エンジンで実行できます。

詳細については、「$group 最適化」を参照してください。

このページの例では、付属の sample_mflixサンプルデータセット のデータを使用します。このデータセットを自己管理型MongoDBデプロイにロードする 方法の詳細については、「サンプルデータセットをロードする 」を参照してください。サンプルデータベースに変更を加えた場合、このページの例を実行するには、データベースを削除して再作成する必要がある場合があります。

次の集計操作では、 $groupステージを使用してmoviesコレクション内のドキュメントの数をカウントします。

db.movies.aggregate([
{
$group: {
_id: null,
count: { $count: {} }
}
}
])
[
{
_id: null,
count: 21349
}
]

この集計操作は、次の SQL ステートメントと同等です。

SELECT COUNT(*) AS count FROM movies

Tip

次の集計操作では、$group ステージを使用して、rated moviesコレクションから個別の 値を取得します。

db.movies.aggregate( [ { $group : { _id : "$rated" } } ] )
[
{
_id: 'TV-PG'
},
{
_id: 'PG'
},
{
_id: 'TV-14'
},
{
_id: 'OPEN'
},
{
_id: 'Not Rated'
},
{
_id: 'GP'
},
{
_id: 'TV-Y7'
},
{
_id: 'G'
},
{
_id: 'PG-13'
},
{
_id: null
},
{
_id: 'M'
},
{
_id: 'R'
},
{
_id: 'TV-MA'
},
{
_id: 'APPROVED'
},
{
_id: 'PASSED'
},
{
_id: 'Approved'
},
{
_id: 'AO'
},
{
_id: 'TV-G'
}
]

注意

$groupを使用してシャーディングされたコレクション内の個別の値を検索する場合、操作の結果が になると、結果にはDISTINCT_SCAN 孤立したドキュメント が含まれる可能性があります。

影響を受けるのはセカンダリが正しいパイプラインのみで、実質的に コマンドの論理的な同等性があります。パイプラインのdistinct $groupまたは 先頭あたりに ステージがあり、 の前には$group $sortステージはありません。 。

例、次の形式の $group 操作の場合、DISTINCT_SCAN が返されます。

{ $group : { _id : "$<field>" } }

個別の値を取得するための動作の詳細については、個別の コマンドの動作を参照してください。

操作の結果がDISTINCT_SCAN になるかどうかを確認するには、操作の explain 結果 を確認します。

次の集計操作では、ドキュメントを ratedフィールドでグループ化し、評価ごとの合計実行時間を計算し、合計実行時間が 100000 以上の評価のみを返します。

db.movies.aggregate(
[
// First Stage
{
$group: {
_id: "$rated",
totalRuntime: { $sum: "$runtime" }
}
},
// Second Stage
{
$match: { "totalRuntime": { $gte: 100000 } }
}
]
)
[
{
_id: 'PG-13',
totalRuntime: 250843
},
{
_id: 'R',
totalRuntime: 582318
},
{
_id: null,
totalRuntime: 967127
},
{
_id: 'PG',
totalRuntime: 191204
}
]
第 1 ステージ:
$groupステージでは、ドキュメントをrated でグループ化し、個別の評価値を取得します。このステージでは、各評価グループのtotalRuntime が返されます。
第 2 ステージ:
ステージでは、結果のドキュメントをフィルタリングして、$match totalRuntime100000が 以上の評価のみを返します。

この集計操作は、次の SQL ステートメントと同等です。

SELECT rated,
Sum(runtime) AS totalRuntime
FROM movies
GROUP BY rated
HAVING totalRuntime >= 100000

次のパイプラインは、1910 以前の各年の合計実行時間、平均実行時間、映画の本数

db.movies.aggregate([
{ $match: { "year": { $lt: 1910 } } },
{
$group: {
_id: "$year",
totalRuntime: { $sum: "$runtime" },
averageRuntime: { $avg: "$runtime" },
count: { $sum: 1 }
}
},
{ $sort: { totalRuntime: -1 } }
])
[
{ _id: 1909, totalRuntime: 14, averageRuntime: 14, count: 1 },
{ _id: 1903, totalRuntime: 11, averageRuntime: 11, count: 1 },
{ _id: 1896, totalRuntime: 2, averageRuntime: 1, count: 2 }
]
第 1 ステージ:
$matchステージでは、ドキュメントをフィルタリングして、1910 より前にリリースされた映画のみを次のステージに渡します。
第 2 ステージ:
$groupステージでは、ドキュメントを年ごとにグループ化し、各グループの合計実行時間、平均実行時間、ドキュメントの合計数を計算します。
第 3 ステージ:
$sortステージでは、各グループの合計実行時間の降順で結果がソートされます。

この集計操作は、次の SQL ステートメントと同等です。

SELECT year,
Sum(runtime) AS totalRuntime,
Avg(runtime) AS averageRuntime,
Count(*) AS count
FROM movies
WHERE year < 1910
GROUP BY year
ORDER BY totalRuntime DESC

Tip

次の集計操作では、null のグループ _id を指定し、コレクション内のすべてのドキュメントの合計実行時間、平均実行時間、カウントを計算します。

db.movies.aggregate([
{
$group: {
_id: null,
totalRuntime: { $sum: "$runtime" },
averageRuntime: { $avg: "$runtime" },
count: { $sum: 1 }
}
}
])
[
{
_id: null,
totalRuntime: 2167458,
averageRuntime: 103.65652797704448,
count: 21349
}
]

この集計操作は、次の SQL ステートメントと同等です。

SELECT Sum(runtime) AS totalRuntime,
Avg(runtime) AS averageRuntime,
Count(*) AS count
FROM movies

Tip

次の集計操作では、moviesコレクションのデータをピボットして、タイトルを年ごとにグループ化します。

db.movies.aggregate([
{ $match: { year: { $lt: 1910 } } },
{ $group: { _id: "$year", titles: { $push: "$title" } } },
{ $sort: { _id: 1 } }
])
[
{ _id: 1896, titles: [ 'The Kiss', 'The Kiss' ] },
{ _id: 1903, titles: [ 'The Great Train Robbery' ] },
{ _id: 1909, titles: [ 'A Corner in Wheat' ] }
]

次の集計操作では、ドキュメントを年ごとにグループ化します。

db.movies.aggregate([
{ $match: { year: { $lt: 1910 } } },
{ $group: { _id: "$year", movies: { $push: "$$ROOT" } } },
{
$addFields: {
totalRuntime: { $sum: "$movies.runtime" }
}
},
{ $sort: { _id: 1 } }
])
[
{ _id: 1896, movies: '...', totalRuntime: 2 },
{ _id: 1903, movies: '...', totalRuntime: 11 },
{ _id: 1909, movies: '...', totalRuntime: 14 }
]
第 1 ステージ:
$match はドキュメントをフィルタリングして、1910 より前にリリースされた映画のみを次のステージに渡します。
第 2 ステージ:
$group$$ROOT システム変数を使用してドキュメント全体を年ごとにグループ化します。
第 3 ステージ:

$addFields 出力に各年の映画の合計実行時間を含むフィールドを追加します。

注意

結果のドキュメントは、BSON ドキュメント サイズの上限である 16 メビバイトを超えてはなりません。

第 4 ステージ:
$sort_idは結果のドキュメントを で昇順にソートします。

このページのC#の例では、Atlasサンプルデータセットsample_mflixデータベースを使用します。MongoDB Atlasクラスターを無料で作成して、サンプルデータセットをロードする方法については、 MongoDB .NET/ C#ドライバーのドキュメントの「 開始 」を参照してください。

次の Movie クラスは、sample_mflix.movies コレクション内のドキュメントをモデル化します。

public class Movie
{
public ObjectId Id { get; set; }
public int Runtime { get; set; }
public string Title { get; set; }
public string Rated { get; set; }
public List<string> Genres { get; set; }
public string Plot { get; set; }
public ImdbData Imdb { get; set; }
public int Year { get; set; }
public int Index { get; set; }
public string[] Comments { get; set; }
[BsonElement("lastupdated")]
public DateTime LastUpdated { get; set; }
}

注意

パスカルケースの ConventionPack

このページのC# クラスはプロパティ名にパスカルケースを使用していますが、MongoDB コレクションのフィールド名はキャメルケースを使用しています。この違いを考慮するために、アプリケーションが起動する際に次のコードを使用してConventionPackを登録してください。

var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);

MongoDB .NET/ C#ドライバーを使用して$group ステージを集計パイプラインに追加するには、 PipelineDefinitionオブジェクトで Group() メソッドを呼び出します。

次の例では、ドキュメントを Ratedフィールドの値でグループ化するパイプラインステージを作成しています。各グループの評価は、各出力ドキュメントの Rating という名前のフィールドに表示されます。各出力ドキュメントには、TotalRuntimeMedianRuntimeNinetiethPercentileRuntime という名前のフィールドも含まれており、各グループの映画の合計、中央値、90 パーセンタイルの実行時間値が保存されます。

var pipeline = new EmptyPipelineDefinition<Movie>()
.Group(
id: m => m.Rated,
group: g => new
{
Rating = g.Key,
TotalRuntime = g.Sum(m => m.Runtime),
MedianRuntime = g.Select(m => m.Runtime).Median(),
NinetiethPercentileRuntime = g.Select(m => m.Runtime).Percentile(new[] { 0.9 })
}
);

このページのNode.js の例では、Atlasサンプルデータセットsample_mflixデータベースを使用します。無料のMongoDB Atlas cluster を作成し、サンプルデータセットをロードする方法については、 MongoDB Node.jsドライバーのドキュメントの開始を参照してください。

MongoDB Node.jsドライバーを使用して $group ステージを集計パイプラインに追加するには、パイプラインオブジェクトで $group 演算子を使用します。

次の例では、ドキュメントを ratedフィールドの値でグループ化するパイプラインステージを作成しています。各出力ドキュメントには、各グループの評価を保存する ratingフィールドが含まれています。各出力ドキュメントには、グループ内のすべての映画の合計ランタイムが保存される totalRuntime という名前のフィールドも含まれています。次に、この例では集計パイプラインを実行します。

const pipeline = [
{
$group: {
_id: "$rated",
rating: { $first: "$rated" },
totalRuntime: { $sum: "$runtime" }
}
}
];
const cursor = collection.aggregate(pipeline);
return cursor;

グループと合計データ」のチュートリアルでは、 一般的なユースケースにおける $group 演算子の幅広い例を紹介します。

関連するパイプラインステージの詳細については、$addFieldsガイドを参照してください。

戻る

$graphLookup

ルール バッジを取得する

「データ変換の基礎」を無料でマスターしましょう!

詳細

項目一覧