AI エージェント向け: ドキュメントインデックスは https://www.mongodb.com/ja-jp/docs/llms.txt で利用できます。すべてのページの markdown バージョンは、いずれかの URL パスに .md を追加することで利用できます。

式、アキュムレータ、およびウィンドウ関数

$avg、$sum、$maxなどの一部の集計演算子は複数のコンテキストに表示され、各コンテキストで演算子の動作が異なります。例:

  • 式として、$avg は配列内の要素の平均を返します。

  • アキュムレータとして、$avgはドキュメントのグループ全体の値の平均を返します。

  • ウィンドウ関数として、$avg はウィンドウ内のドキュメントの値の平均を返します。

演算子を含むステージによって、その動作が決まります。同じ演算子名でも、使用する場所によって異なる引数を受け入れ、異なる結果を返すことがあります。このページでは、3つのコンテキストと、それらを明確に区別する方法について説明します。

次の図は、式、アキュムレータ、ウィンドウ関数がどのように実行されるかを概念化したものです。

次の表は、3つの演算子タイプの違いをまとめたものです。

演算子タイプ
動作
使用できる場所

式

各入力ドキュメントに対して評価され、ドキュメントごとに 1 つの値を返します。

$project、$addFields、その他多くのステージに加え、$expr述語やfindコマンドのプロジェクションなどがあります。

アキュムレータ

入力ドキュメントのグループに対して集計を行い、グループごとに1つの集計値を返します。

ウィンドウ関数

入力ドキュメントのウィンドウに対して評価され、ドキュメントごとに1つの値を返します。

式は、単一の入力ドキュメントの値に解決されます。式は入力を変更しません。

式演算子は引数の配列を受け入れ、次の汎用形式をとります。

{ <operator>: [ <argument1>, <argument2> ... ] }

演算子が引数を 1 つだけ受け入れる場合は、外側の配列を省略できます。

式は、アキュムレータやウィンドウ関数の引数も提供します。たとえば、{ $sum: "$price" } では、フィールドパス "$price" が式です。

詳細については、「式」を参照してください。

アキュムレータは、可変数の入力ドキュメント全体にわたって、合計、最大値、最小値などの単一の集計値を計算します。実際の実装では、アキュムレータはグループ化操作の実行中に処理するドキュメント間で状態を維持します。

$group ステージによって返される出力ドキュメントの数は、グループの数と等しくなります。これらの各グループに対して、アキュムレータはグループ全体の集計値を計算します。

グループ化操作を実行する集計パイプラインステージでアキュムレータを使用できます。

詳細については、アキュムレータを参照してください。

ウィンドウ関数は、現在のドキュメントに対して定義されたドキュメントの範囲であるウィンドウに基づいて値を返します。ウィンドウは、$setWindowFieldsステージのpartitionBy、sortBy、およびwindowフィールドで定義します。

アキュムレータとウィンドウ関数の両方として機能する演算子の場合、その違いは、演算子が何を対象に集計するか、そしていくつの値を返すかという点にあります。

  • アキュムレータとして、この演算子はドキュメントのグループを集計し、そのグループに対して単一の値を返します。

  • ウィンドウ関数として、この演算子はドキュメントのウィンドウ全体を集計し、各ドキュメントの値を返します。

ウィンドウ関数は、$setWindowFields ステージでのみ使用できます。$setWindowFields は、$rank や $shift など、Windows に固有の演算子もサポートしています。

詳しくは、「ウィンドウ関数」を参照してください。

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

以下の例では、これら3つのコンテキストすべてで $sum を使用しています。それぞれが異なる結果を返すため、コンテキストによって演算子の動作がどのように決定されるかがわかります。

次の例では、$sum を式として使用し、各ドキュメント内の 2 つのフィールドを加算します。パイプラインは、一致する各ドキュメントに対して 1 つの合計を返します。

db.movies.aggregate( [ { $match: { title: { $in: [ "The Godfather", "Inception", "The Dark Knight" ] } } }, { $project: { _id: 0, title: 1, totalAwards: { $sum: [ "$awards.wins", "$awards.nominations" ] } } }, { $sort: { totalAwards: -1 } }] )

次の例では、$sumをアキュムレータとして使用し、各グループ内のすべてのドキュメントにわたって1つのフィールドを合計します。パイプラインは、ドキュメントごとの合計ではなく、コンテンツ評価ごとの合計を返します。

db.movies.aggregate( [ { $match: { rated: { $in: [ "G", "PG", "PG-13", "R" ] }, "imdb.votes": { $type: "int" } } }, { $group: { _id: "$rated", totalVotes: { $sum: "$imdb.votes" } } }, { $sort: { _id: 1 } }] )

次の例では、$sumをウィンドウ関数として使用し、ドキュメントのウィンドウ全体で1つのフィールドを合計します。パイプラインは各ドキュメントの累計を返し、その合計はドキュメントのウィンドウによって異なります。

db.movies.aggregate( [ { $match: { genres: "Musical", year: { $in: [ 2009, 2010 ] }, "imdb.rating": { $type: "double" }, "imdb.votes": { $gt: 0 } } }, { $setWindowFields: { partitionBy: "$year", sortBy: { title: 1 }, output: { cumulativeVotesInYear: { $sum: "$imdb.votes", window: { documents: [ "unbounded", "current" ] } }, rankInYear: { $documentNumber: {} } } } }, { $project: { _id: 0, title: 1, year: 1, "imdb.votes": 1, cumulativeVotesInYear: 1, rankInYear: 1 } }, { $sort: { year: 1, title: 1 } }] )