集計
定義
aggregate
集計パイプラインを使用して集計操作を実行します。 パイプラインを使用すると、ユーザーはコレクションやその他のソースからのデータをステージベース操作のシークエンスで処理できます。
Tip
mongosh
では、このコマンドはdb.aggregate()
ヘルパー メソッドおよびdb.collection.aggregate()
ヘルパー メソッドで実行できます。またはwatch()
ヘルパー メソッドを使用することも可能です。ヘルパー メソッドは
mongosh
ユーザーには便利ですが、データベースコマンドと同じレベルの情報は返されない可能性があります。 便宜上必要ない場合、または追加の戻りフィールドが必要な場合は、 データベースコマンドを使用します。
互換性
このコマンドは、次の環境でホストされている配置で使用できます。
MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
重要
このコマンドは、M 0 、M 2 、および M 5クラスターで限定的にサポートされています。 詳細については、「サポートされていないコマンド 」を参照してください。
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
バージョン 5.0 での変更。
このコマンドの構文は、次のとおりです。
db.runCommand( { aggregate: "<collection>" || 1, pipeline: [ <stage>, <...> ], explain: <boolean>, allowDiskUse: <boolean>, cursor: <document>, maxTimeMS: <int>, bypassDocumentValidation: <boolean>, readConcern: <document>, collation: <document>, hint: <string or document>, comment: <any>, writeConcern: <document>, let: <document> // Added in MongoDB 5.0 } )
コマンドフィールド
aggregate
コマンドは、次のフィールドを引数として受け取ります。
フィールド | タイプ | 説明 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
aggregate | string | 集約パイプラインへの入力となるコレクションまたはビューの名前。コレクションに依存しないコマンドには 1 を使用します。 | ||||||||||
pipeline | 配列 | 集計パイプラインの一部としてドキュメントストリームを処理および変換する集計パイプライン ステージの配列。 | ||||||||||
explain | ブール値 | 任意。パイプラインの処理に関する情報を返すように指定します。 マルチドキュメントトランザクションでは使用できません。 | ||||||||||
| ブール値 | 任意。 このオプションを使用して、特定のクエリの
MongoDB 6.0 以降では、 詳細については、 プロファイラー ログ メッセージと診断ログ メッセージには、メモリ制限のために集計ステージで一時ファイルにデータが書込まれた場合、 | ||||||||||
cursor | ドキュメント | カーソルオブジェクト作成を制御するオプションを含めたドキュメントを指定。 MongoDB は、
| ||||||||||
maxTimeMS | non-negative integer | 任意。 時間制限をミリ秒単位で指定します。 MongoDB は、 | ||||||||||
bypassDocumentValidation | ブール値 | |||||||||||
readConcern | ドキュメント | 任意。読み取り保証 (read concern) を指定します。
次の読み取り保証レベルが利用できます。
読み取り保証 (read concern) のレベルについて詳しくは、「読み取り保証 (read concern) レベル」を参照してください。
| ||||||||||
collation | ドキュメント | 任意。 操作に使用する照合を指定します。 照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。 照合オプションの構文は次のとおりです。
照合を指定する場合、 照合が指定されていなくても、コレクションにデフォルトの照合が設定されている場合( コレクションにも操作にも照合が指定されていない場合、MongoDB では以前のバージョンで使用されていた単純なバイナリ比較によって文字列が比較されます。 1 つの操作に複数の照合は指定できません。たとえば、フィールドごとに異なる照合を指定できません。また、ソートと検索を一度に実行する場合、検索とソートで別の照合を使用できません。 | ||||||||||
hint | 文字列またはドキュメント | 任意。集計に使用するインデックス。インデックスは、集計が実行される最初のコレクションまたはビューにあります。 インデックス名、またはインデックス仕様ドキュメントのいずれかによってインデックスを指定します。
| ||||||||||
comment | any | 任意。このコマンドに添付するユーザー指定のコメント。設定すると、このコメントは以下の場所にこのコマンドの記録と合わせて表示されます。
コメントには、有効な BSON 型(string, integer, object, array など)を使用できます。
| ||||||||||
writeConcern | ドキュメント | 任意。または | ||||||||||
let | ドキュメント | 任意。 変数のリストを含むドキュメントを指定します。これにより、変数をクエリテキストから分離することで、コマンドの読みやすさを向上させることができます。 ドキュメントの構文は次のとおりです。
変数は式によって返された値に設定され、その後は変更できません。 コマンド内の変数の値にアクセスするには、二重ドル記号の接頭辞( パイプライン
バージョン 5.0 で追加 |
MongoDB は、aggregate
コマンドが explain
オプションを含まない場合は、cursor
オプションを含まないこのコマンドの使用を削除します。explain
オプションを含まない場合は、カーソル オプションを指定する必要があります。
デフォルトのバッチ サイズのカーソルを示すには、
cursor: {}
を指定します。デフォルト以外のバッチ サイズのカーソルを示すには、
cursor: { batchSize: <num> }
を使用します。
集計パイプラインの詳細については、以下を参照してください。
セッション
セッション内で作成されたカーソルの場合、セッション外で getMore
を呼び出すことはできません。
同様に、セッション外で作成されたカーソルの場合、セッション内で getMore
を呼び出すことはできません。
セッション アイドル タイムアウト
MongoDB ドライバーとmongosh
では、確認されていない書込み操作を除くすべての操作がサーバー セッションに関連付けられます。セッションに明示的に関連付けられていない操作(つまり Mongo.startSession()
を使用するもの)の場合、MongoDB ドライバーとmongosh
によって暗黙的なセッションが作成され、それが操作に関連付けられます。
セッションが30分以上アイドル状態になると、MongoDBサーバーはそのセッションを期限切れとしてマークし、いつでも閉じる可能性があります。MongoDB サーバーでセッションが閉じると、そのセッションで進行中の操作や開いているカーソルもすべて終了します。これには、noCursorTimeout()
や 30 分を超える maxTimeMS()
で構成されたカーソルも含まれます。
カーソルを返す操作の場合、カーソルが 30 分以上アイドル状態になる可能性がある場合は、 Mongo.startSession()
を使用して明示的なセッション内で操作を発行し、 refreshSessions
コマンドを使用して定期的にセッションを更新します。詳細については、セッションアイドルタイムアウトを参照してください。
トランザクション
aggregate
は分散トランザクション内で使用できます。
ただし、トランザクション内では以下のステージは許可されません。
また、explain
オプションも指定できません。
トランザクションの外部で作成されたカーソルの場合、トランザクション内で
getMore
を呼び出せません。トランザクション内で作成されたカーソルの場合、トランザクション外で
getMore
を呼び出せません。
重要
ほとんどの場合、分散トランザクションでは 1 つのドキュメントの書き込み (write) よりもパフォーマンス コストが高くなります。分散トランザクションの可用性は、効果的なスキーマ設計の代わりにはなりません。多くのシナリオにおいて、非正規化されたデータモデル(埋め込みドキュメントと配列)が引き続きデータやユースケースに最適です。つまり、多くのシナリオにおいて、データを適切にモデリングすることで、分散トランザクションの必要性を最小限に抑えることができます。
トランザクションの使用に関するその他の考慮事項(ランタイム制限や oplog サイズ制限など)については、「本番環境での考慮事項」も参照してください。
クライアントの切断
$out
ステージまたは $merge
ステージを含まない aggregate
操作の場合。
MongoDB 4.2以降では、 aggregate
を発行したクライアントが操作の完了前に切断した場合、MongoDB は killOp
を使用してaggregate
を終了対象としてマークし 。
クエリ設定
バージョン8.0の新機能。
クエリ設定を使用して、インデックスヒント、操作拒否フィルター、その他のフィールドを設定できます。設定はクラスター全体のクエリシェイプに適用されます。クラスターは、シャットダウン後も設定を保持します。
クエリオプティマイザは、クエリプランニング中の追加入力としてクエリ設定を使用します。これは、クエリを実行するために選択されたプランに影響します。クエリ設定を使用してクエリシェイプをブロックすることもできます。
クエリ設定を追加して例を調べるには、setQuerySettings
を参照してください。
find
、distinct
、および aggregate
コマンドのクエリ設定を追加できます。
クエリ設定にはより多くの機能があり、廃止されたインデックスフィルターよりも優先されます。
クエリ設定を削除するには、 removeQuerySettings
を使用します。 クエリ設定を取得するには、集計パイプラインの$querySettings
ステージを使用します。
Stable API
Stable API V1 を使用する場合
aggregate
コマンドでは次に挙げるステージは使用できません。aggregate
コマンドにexplain
フィールドを含めないでください。その場合サーバーは APIStrictError エラーを返します。$collStats
ステージを使用する場合、使用できるのはcount
フィールドのみです。他の$collStats
フィールドは使用できません。
例
MongoDB は、aggregate
コマンドが explain
オプションを含まない場合は、cursor
オプションを含まないこのコマンドの使用を削除します。explain
オプションを含まない場合は、カーソル オプションを指定する必要があります。
デフォルトのバッチ サイズのカーソルを示すには、
cursor: {}
を指定します。デフォルト以外のバッチ サイズのカーソルを示すには、
cursor: { batchSize: <num> }
を使用します。
aggregate
コマンドを直接実行するのではなく、むしろほとんどのユーザーは mongosh
で提供される db.collection.aggregate()
ヘルパーまたはドライバー内の同等のヘルパーを使用する必要があります。2.6 以降では db.collection.aggregate()
ヘルパーは常にカーソルを返します。
コマンド構文を示す最初の 2 つの例を除き、このページの例では db.collection.aggregate()
ヘルパーを使用します。
マルチステージパイプラインによるデータの集約
コレクション articles
には次のドキュメントが含まれています。
{ _id: ObjectId("52769ea0f3dc6ead47c9a1b2"), author: "abc123", title: "zzz", tags: [ "programming", "database", "mongodb" ] }
次の例では articles
コレクションに aggregate
操作を実行し、コレクション内に表示される tags
配列内の各個別要素の数を計算します。
db.runCommand( { aggregate: "articles", pipeline: [ { $project: { tags: 1 } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum : 1 } } } ], cursor: { } } )
mongosh
では、この操作は次のように db.collection.aggregate()
ヘルパーを使用できます。
db.articles.aggregate( [ { $project: { tags: 1 } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum : 1 } } } ] )
管理データベースでの $currentOp の使用
次の例では、管理データベースで 2 つのステージを持つパイプラインを実行します。最初のステージでは $currentOp
操作を実行し、2 番目のステージではその操作の結果をフィルタリングします。
db.adminCommand( { aggregate : 1, pipeline : [ { $currentOp : { allUsers : true, idleConnections : true } }, { $match : { shard : "shard01" } } ], cursor : { } } )
注意
aggregate
コマンドはコレクションを指定せず、代わりに {aggregate: 1}
の形式を取ります。これは、最初の $currentOp
ステージではコレクションから入力が取得されないためです。パイプラインの残りの部分で使用される独自のデータを生成します。
こうしたコレクションレス集計の実行を支援するために、新しい db.aggregate()
ヘルパーが追加されました。上の集計はこの例のように実行することもできます。
集計操作の情報を返す
次の集計操作では、任意フィールド explain
を true
に設定して、集計操作に関する情報を返します。
db.orders.aggregate([ { $match: { status: "A" } }, { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, { $sort: { total: -1 } } ], { explain: true } )
注意
explain の出力は、リリース間で変更される可能性があります。
相互作用: allowDiskUseByDefault
MongoDB 6.0 以降、 100 MB 以上のメモリを必要とするパイプライン ステージでは、デフォルトで一時ファイルをディスクに書き込みます。これらの一時ファイルはパイプラインの実行中ずっと残り、インスタンスのストレージ容量に影響を与える可能性があります。以前のバージョンの MongoDB では、この動作を有効にするには、個々の find
コマンドと aggregate
コマンドに { allowDiskUse: true }
を渡す必要がありました。
個々の find
と aggregate
コマンドは、次のいずれかの方法で allowDiskUseByDefault
パラメーターを上書きできます。
allowDiskUseByDefault
がfalse
に設定されている場合に{ allowDiskUse: true }
を使用して一時ファイルをディスクに書き込むことを許可するallowDiskUseByDefault
がtrue
に設定されている場合に{ allowDiskUse: false }
を使用して一時ファイルがディスクに書き込むことを禁止する
プロファイラー ログ メッセージと診断ログ メッセージには、メモリ制限のために集計ステージで一時ファイルにデータが書込まれた場合、usedDisk
インジケーターが含められます。
バッチサイズを指定する集計データ
初期バッチサイズを指定するには、下記の例のように cursor
フィールドに batchSize
を指定します。
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
フィールドを使用します。
照合の指定
照合を指定すると、大文字・小文字やアクセント記号など、文字列を比較するための言語独自のルールを指定できます。
コレクション myColl
は、次のドキュメントを含みます。
{ _id: 1, category: "café", status: "A" } { _id: 2, category: "cafe", status: "a" } { _id: 3, category: "cafE", status: "a" }
下記の集計操作には 照合オプションが含まれます。
db.myColl.aggregate( [ { $match: { status: "A" } }, { $group: { _id: "$category", count: { $sum: 1 } } } ], { collation: { locale: "fr", strength: 1 } } );
照合フィールドの説明については、照合ドキュメントを参照してください。
インデックスの hint
次のドキュメントを使用してコレクション foodColl
を作成します。
db.foodColl.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.foodColl.createIndex( { qty: 1, type: 1 } ); db.foodColl.createIndex( { qty: 1, category: 1 } );
下記の集計操作には、指定されたインデックスの使用を強制する hint
オプションが含まれています。
db.foodColl.aggregate( [ { $sort: { qty: 1 }}, { $match: { category: "cake", qty: 10 } }, { $sort: { type: -1 } } ], { hint: { qty: 1, category: 1 } } )
デフォルトの読み取り保証を上書き
デフォルトの読み取り保証 (read concern) レベルを上書きするには、readConcern
オプションを使用します。getMore
コマンドは、元の aggregate
コマンドで指定された readConcern
レベルを使用します。
$out
または $merge
ステージを、読み取り保証 "linearizable"
と組み合わせて使用することはできません。つまり、"linearizable"
読み取り保証を db.collection.aggregate()
に対して指定した場合は、どちらのステージもパイプライン内に含めることができません。
レプリカセットに対する次の操作では、大多数のノードに書き込まれたことが確認されたデータの最新のコピーを読み取るために、読み取り保証"majority"
を指定します。
重要
$out
ステージを含む集計に対して、読み取り保証レベル"majority"
を指定できます。読み取り保証のレベルを問わず、ノード上の最新データにシステム内のデータの最新バージョンが反映されていない場合があります。
db.restaurants.aggregate( [ { $match: { rating: { $lt: 5 } } } ], { readConcern: { level: "majority" } } )
単一のスレッドでそれ自体の書き込みの読み取りを可能にするには、レプリカセットのプライマリに対して "majority"
読み取り保証と "majority"
書込み保証を使用します。
変数の使用 let
バージョン 5.0 で追加
コマンド内の他の場所からアクセスできる変数を定義するには、 let
オプションを使用します。
さまざまなフレーバーのケーキの売上情報を含むコレクション 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 のケーキを検索します。let
でtargetTotal
変数を定義します。これは$gt
で$$targetTotal
として参照されます。
db.runCommand( { aggregate: db.cakeSales.getName(), pipeline: [ { $match: { $expr: { $gt: [ "$salesTotal", "$$targetTotal" ] } } }, ], cursor: {}, let: { targetTotal: 3000 } } )