Docs Menu

db.collection.aggregate()

MongoDB とドライバー

このページではmongoshメソッドがドキュメントされています。 MongoDB ドライバーで同等のメソッドを確認するには、プログラミング言語の対応するページを参照してください。

db.collection.aggregate(pipeline, options)

コレクションまたはビュー内のデータの集計値を計算します。

次の値を返します。
  • 集計パイプラインの最終ステージ段階で作成されたドキュメント用のカーソル。
  • パイプラインに explain オプションが含まれている場合、クエリが返すドキュメントには集計操作の処理が詳述されています。
  • パイプラインに $out 演算子または $merge 演算子が含まれている場合、クエリは空のカーソルを返します。

次の環境でホストされる配置には db.collection.aggregate() を使用できます。

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

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

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

aggregate() メソッドの形式は次のとおりです。

db.collection.aggregate( <pipeline>, <options> )

aggregate() メソッドは次のパラメーターを取ります。

Parameter
タイプ
説明

pipeline

配列

データ集計の一連の操作またはステージ。 詳細については、集計パイプライン演算子を参照してください。

このメソッドでは、配列の要素としてではなく、個別の引数としてパイプライン ステージを受け入れ可能ですが、pipeline を配列として指定しない場合、options パラメーターを指定できません。

options

ドキュメント

任意。 aggregate()aggregate コマンドに渡す追加オプション。pipeline を配列として指定した場合にのみ使用できます。 利用可能なオプションを確認するには、「 AggregateOptions 」を参照してください。

エラーが発生した場合、aggregate() ヘルパーは例外をスローします。

mongosh では、db.collection.aggregate() から返されたカーソルが var キーワードを使用して変数に割り当てられていない場合、mongosh は最大 20 回までカーソルを自動的に反復します。mongosh でのカーソルの処理については、「mongosh でのカーソルの反復処理」を参照してください。

集計から返されるカーソルは、評価済みカーソル(最初のバッチが取得されたカーソル)で動作する次のようなカーソル メソッドのみをサポートします。

詳細については、以下を参照してください。

セッション内で作成されたカーソルの場合、セッション外で getMore を呼び出すことはできません。

同様に、セッション外で作成されたカーソルの場合、セッション内で getMore を呼び出すことはできません。

MongoDB ドライバーとmongosh では、確認されていない書込み操作を除くすべての操作がサーバー セッションに関連付けられます。セッションに明示的に関連付けられていない操作(つまり Mongo.startSession()を使用するもの)の場合、MongoDB ドライバーとmongoshによって暗黙的なセッションが作成され、それが操作に関連付けられます。

セッションが30分以上アイドル状態になると、MongoDBサーバーはそのセッションを期限切れとしてマークし、いつでも閉じる可能性があります。MongoDB サーバーでセッションが閉じると、そのセッションで進行中の操作や開いているカーソルもすべて終了します。これには、noCursorTimeout() や 30 分を超える maxTimeMS() で構成されたカーソルも含まれます。

カーソルを返す操作の場合、カーソルが 30 分以上アイドル状態になる可能性がある場合は、 Mongo.startSession() を使用して明示的なセッション内で操作を発行し、 refreshSessions コマンドを使用して定期的にセッションを更新します。詳細については、セッションアイドルタイムアウトを参照してください。

db.collection.aggregate()分散トランザクション内で使用できます。

ただし、トランザクション内では以下のステージは許可されません。

また、explain オプションも指定できません。

  • トランザクションの外部で作成されたカーソルの場合、トランザクション内で getMore を呼び出せません。

  • トランザクション内で作成されたカーソルの場合、トランザクション外で getMore を呼び出せません。

重要

ほとんどの場合、分散トランザクションでは 1 つのドキュメントの書き込み (write) よりもパフォーマンス コストが高くなります。分散トランザクションの可用性は、効果的なスキーマ設計の代わりにはなりません。多くのシナリオにおいて、非正規化されたデータモデル(埋め込みドキュメントと配列)が引き続きデータやユースケースに最適です。つまり、多くのシナリオにおいて、データを適切にモデリングすることで、分散トランザクションの必要性を最小限に抑えることができます。

トランザクションの使用に関するその他の考慮事項(ランタイム制限や oplog サイズ制限など)については、「本番環境での考慮事項」も参照してください。

$out ステージまたは $merge ステージを含まない db.collection.aggregate() 操作の場合。

MongoDB 4.2以降では、 db.collection.aggregate()を発行したクライアントが操作の完了前に切断した場合、MongoDB は killOp を使用してdb.collection.aggregate()を終了対象としてマークし

バージョン8.0の新機能

クエリ設定を使用して、インデックスヒント、操作拒否フィルター、その他のフィールドを設定できます。設定はクラスター全体のクエリシェイプに適用されます。クラスターは、シャットダウン後も設定を保持します。

クエリオプティマイザは、クエリプランニング中の追加入力としてクエリ設定を使用します。これは、クエリを実行するために選択されたプランに影響します。クエリ設定を使用してクエリシェイプをブロックすることもできます。

クエリ設定を追加して例を調べるには、setQuerySettings を参照してください。

finddistinctaggregate コマンドのクエリ設定を追加できます。

クエリ設定にはより多くの機能があり、廃止されたインデックスフィルターよりも優先されます。

クエリ設定を削除するには、 removeQuerySettingsを使用します。 クエリ設定を取得するには、集計パイプラインの$querySettingsステージを使用します。

以下の例では、次のドキュメントを含むコレクション orders を使用します。

db.orders.insertMany( [
{ _id: 1, cust_id: "abc1", ord_date: ISODate("2012-11-02T17:04:11.102Z"), status: "A", amount: 50 },
{ _id: 2, cust_id: "xyz1", ord_date: ISODate("2013-10-01T17:04:11.102Z"), status: "A", amount: 100 },
{ _id: 3, cust_id: "xyz1", ord_date: ISODate("2013-10-12T17:04:11.102Z"), status: "D", amount: 25 },
{ _id: 4, cust_id: "xyz1", ord_date: ISODate("2013-10-11T17:04:11.102Z"), status: "D", amount: 125 },
{ _id: 5, cust_id: "abc1", ord_date: ISODate("2013-11-12T17:04:11.102Z"), status: "A", amount: 25 }
] )

次の集計操作では、ステータスが "A" と等しいドキュメントを選択し、一致するドキュメントをcust_id フィールドでループ化し、amount フィールドの合計から各cust_id フィールドの total を計算し、結果をtotal フィールドで降順にソートします。

db.orders.aggregate( [
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } }
] )

この操作は、次のドキュメントを持つカーソルを返します。

[
{ _id: "xyz1", total: 100 },
{ _id: "abc1", total: 75 }
]

mongosh は返されたカーソルを自動的に反復して結果を出力します。でカーソルを手動で処理する方法については mongosh でカーソルを手動で処理する方法については、「mongosh でのカーソルの反復処理」を参照してください。

次の例では、db.collection.explain() を使用して、集計パイプラインの実行プランに関する詳細情報を表示します。

db.orders.explain().aggregate( [
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } }
] )

この操作は集計パイプラインの処理を詳述するドキュメントを返します。 たとえば、このドキュメントにはどのインデックスが操作に使用されたかなどの詳細が示されます。 [ 1 ] ordersコレクションがシャーディングされたコレクションの場合は、シャード間の作業分担やマージ操作、ターゲットクエリの場合にはターゲットシャードもドキュメントに表示されます。

注意

explain 出力ドキュメントの対象読者は機械ではなく人間であり、出力形式はリリース間で変更される可能性があります。

executionStats または allPlansExecution 説明モードを db.collection.explain() メソッドに渡すと、より冗長な説明出力を表示できます。

[1] インデックス フィルターは使用インデックスの選択に影響する可能性があります。詳細については、「インデックス フィルター」を参照してください。

MongoDB 6.0 以降、 100 MB 以上のメモリを必要とするパイプライン ステージでは、デフォルトで一時ファイルをディスクに書き込みます。これらの一時ファイルはパイプラインの実行中ずっと残り、インスタンスのストレージ容量に影響を与える可能性があります。以前のバージョンの MongoDB では、この動作を有効にするには、個々の find コマンドと aggregate コマンドに { allowDiskUse: true } を渡す必要がありました。

個々の findaggregate コマンドは、次のいずれかの方法で allowDiskUseByDefault パラメーターを上書きできます。

  • allowDiskUseByDefaultfalse に設定されている場合に { allowDiskUse: true } を使用して一時ファイルをディスクに書き込むことを許可する

  • allowDiskUseByDefaulttrue に設定されている場合に { allowDiskUse: false } を使用して一時ファイルがディスクに書き込むことを禁止する

プロファイラー ログ メッセージ診断ログ メッセージには、メモリ制限のために集計ステージで一時ファイルにデータが書込まれた場合、usedDisk インジケーターが含められます。

詳細については、「集計パイプラインの制限」を参照してください。

カーソルの初期バッチ サイズを指定するには、cursor オプションに次の構文を使用します。

cursor: { batchSize: <int> }

たとえば、次の集計操作では、カーソルの初期バッチサイズとして 0 を指定します。

db.orders.aggregate(
[
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } },
{ $limit: 2 }
],
{
cursor: { batchSize: 0 }
}
)

初期バッチのサイズを指定する { cursor: { batchSize: 0 } } ドキュメントは、1 個めのバッチが空であることを示します。このバッチサイズは、サーバー側での目立った作業なしに、カーソルやエラーメッセージをすばやく返すのに便利です。

後続の getMore 操作(最初のバッチの後)のバッチ サイズを指定するには、getMore コマンドを実行する際に batchSize フィールドを使用します。

mongosh は返されたカーソルを自動的に反復して結果を出力します。でカーソルを手動で処理する方法については mongosh でカーソルを手動で処理する方法については、「mongosh でのカーソルの反復処理」を参照してください。

照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。

コレクション restaurantsは、次のドキュメントを含みます。

db.restaurants.insertMany( [
{ _id: 1, category: "café", status: "A" },
{ _id: 2, category: "cafe", status: "a" },
{ _id: 3, category: "cafE", status: "a" }
] )

次の集計操作には 照合オプションが含まれます。

db.restaurants.aggregate(
[ { $match: { status: "A" } }, { $group: { _id: "$category", count: { $sum: 1 } } } ],
{ collation: { locale: "fr", strength: 1 } }
);

注意

複数のビューが関わる集計($lookup$graphLookup など)が実行される場合、それらのビューには同じ照合が含まれる必要があります。

照合フィールドの説明については、照合ドキュメントを参照してください。

次のドキュメントを使用してコレクション food を作成します。

db.food.insertMany( [
{ _id: 1, category: "cake", type: "chocolate", qty: 10 },
{ _id: 2, category: "cake", type: "ice cream", qty: 25 },
{ _id: 3, category: "pie", type: "boston cream", qty: 20 },
{ _id: 4, category: "pie", type: "blueberry", qty: 15 }
] )

下記のインデックスを作成します。

db.food.createIndex( { qty: 1, type: 1 } );
db.food.createIndex( { qty: 1, category: 1 } );

下記の集計操作には、指定されたインデックスの使用を強制する hint オプションが含まれています。

db.food.aggregate(
[ { $sort: { qty: 1 }}, { $match: { category: "cake", qty: 10 } }, { $sort: { type: -1 } } ],
{ hint: { qty: 1, category: 1 } }
)

操作の読み取り保証(read concern)を指定するには、readConcern オプションを使用します。

$out または $merge ステージは、読み取り保証 "linearizable" と組み合わせて使用できません。そのため、"linearizable" の読み取り保証を db.collection.aggregate() に対して指定した場合、いずれのステージもパイプラインに含めることはできません。

レプリカセットに対する次の操作では、大多数のノードに書き込まれたことが確認されたデータの最新のコピーを読み取るために、"majority"読み取り保証を指定します。

注意

  • 単一のスレッドでそれ自体の書き込みの読み取りを可能にするには、レプリカセットのプライマリに対して "majority" 読み取り保証と "majority" 書込み保証を使用します。

  • $out ステージを含む集計に対して、読み取り保証レベル "majority" を指定できます。

  • 読み取り保証のレベルを問わず、ノード上の最新データにシステム内のデータの最新バージョンが反映されていない場合があります。

db.restaurants.aggregate(
[ { $match: { rating: { $lt: 5 } } } ],
{ readConcern: { level: "majority" } }
)

コレクション「movies」には次のような形式のドキュメントが含まれています。

db.movies.insertOne(
{
_id: ObjectId("599b3b54b8ffff5d1cd323d8"),
title: "Jaws",
year: 1975,
imdb: "tt0073195"
}
)

次の集計操作では、1995 年に制作された映画が検索し、comment オプションを含めて、logsdb.system.profile コレクション、およびdb.currentOp 内の追跡情報を提供します。

db.movies.aggregate( [ { $match: { year : 1995 } } ], { comment : "match_all_movies_from_1995" } ).pretty()

プロファイリングが有効になっているシステムでは、以下で示すように、system.profile コレクションにクエリを実行して、すべての最新の類似した集計を確認できます。

db.system.profile.find( { "command.aggregate": "movies", "command.comment" : "match_all_movies_from_1995" } ).sort( { ts : -1 } ).pretty()

このクエリでは、プロファイラーの結果セットが次の形式で返されます。

{
"op" : "command",
"ns" : "video.movies",
"command" : {
"aggregate" : "movies",
"pipeline" : [
{
"$match" : {
"year" : 1995
}
}
],
"comment" : "match_all_movies_from_1995",
"cursor" : {
},
"$db" : "video"
},
...
}

アプリケーションは、システム内の特定の操作をより簡単に追跡または識別できるように、コメントに任意の情報をエンコードできます。たとえば、プロセス ID、スレッド ID、クライアントのホスト名、コマンドを発行したユーザーを含む文字列コメントを添付できます。

バージョン 5.0 で追加

コマンド内の他の場所からアクセスできる変数を定義するには、 letオプションを使用します。

注意

パイプライン $match ステージで変数を使用して結果をフィルター処理するには $expr 演算子内で変数にアクセスする必要があります。

さまざまなフレーバーのケーキの売上情報を含むコレクション cakeSales を作成するとします。

db.cakeSales.insertMany( [
{ _id: 1, flavor: "chocolate", salesTotal: 1580 },
{ _id: 2, flavor: "strawberry", salesTotal: 4350 },
{ _id: 3, flavor: "cherry", salesTotal: 2150 }
] )

次の例:

  • salesTotal が3000より大きいケーキ、つまり _id が 2 のケーキを検索します。

  • lettargetTotal 変数を定義します。これは $gt$targetTotal として参照されます。

db.cakeSales.aggregate(
[
{ $match: {
$expr: { $gt: [ "$salesTotal", "$$targetTotal" ] }
} }
],
{ let: { targetTotal: 3000 } }
)