定義
$facet同じ入力ドキュメントセット上の単一ステージ内の複数の 集計パイプラインを処理します。各サブパイプラインには出力ドキュメントに独自のフィールドがあり、その結果はドキュメントの配列として保存されます。
$facetステージでは、1 つの集計ステージ内で複数のディメンションまたはファセットにわたるデータを特徴付ける多面的な集計を作成できます。ファセット集計により、データの参照と分析をガイドする複数のフィルターと分類が提供されます。小売業者は通常、商品の価格、メーカー、サイズなどのフィルターを作成して検索結果を絞り込むためにファセットを使用します。入力ドキュメントは
$facetステージに一度だけ渡されるため、同じ入力ドキュメント セットに対して様々な集計を実行できます。
互換性
次の環境でホストされる配置には $facet を使用できます。
MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
$facetステージの形式は次のとおりです。
{ $facet: { <outputField1>: [ <stage1>, <stage2>, ... ], <outputField2>: [ <stage1>, <stage2>, ... ], ... } }
指定した各パイプラインの出力フィールド名を指定します。
Considerations
$facetの各ステージが実行されると、結果のドキュメントは 100 メガバイトに制限されます。$facetディスクに書き出すことができないため、 allowDiskUseフラグは 100 メガバイトのサイズ制限に影響しないことに注意してください。
最終出力ドキュメントは、16 メビバイトの BSON ドキュメント サイズ制限の対象となります。16 メビバイトを超えると、集計でエラーが発生します。
Tip
動作
ファセット関連の集計ステージでは、受信したドキュメントを分類してグループ化します。さまざまな $facet サブパイプラインの <stage> 内の以下のファセット関連ステージのいずれかを指定して、多面的な集計を実行します。
$facet では他の集計ステージも使用できます。ただし、次の例外があります。
$facet内の各サブパイプラインには、まったく同じ入力ドキュメントのセットが渡されます。これらのサブパイプラインは互いに完全に独立しており、それぞれのドキュメント配列出力は出力ドキュメントの別々のフィールドに保存されます。 1 つのサブパイプラインの出力を、同じ $facet ステージ内の別のサブパイプラインの入力として使用することはできません。 さらに集計が必要な場合は、$facet の後にステージを追加し、目的のサブパイプライン出力のフィールド名 <outputField> を指定します。
インデックスの使用
パイプラインの順序によって、 $facetステージがインデックスを使用する方法が決まります。
$facetステージがパイプラインの最初のステージである場合、ステージはCOLLSCANを実行します。$facetステージは、パイプラインの最初のステージである場合、インデックスを使用しません。$facetステージがパイプラインの後半にあり、前のステージでインデックスが使用されている場合、$facetの実行中はCOLLSCANはトリガーされません。
たとえば、$facet ステージよりも前にある$match または$sort ステージはインデックスを使用することができ、$facet ステージはCOLLSCAN をトリガーしません。
最適化の提案については、「集計パイプラインの最適化」を参照してください。
例
このページの例では、sample_mflixサンプルデータセットのデータを使用します。このデータセットを自己管理型MongoDB配置にロードする方法の詳細については、サンプルデータセットをロードする を参照してください。サンプルデータベースに変更を加えた場合、このページの例を実行するには、データベースを削除して再作成する必要がある場合があります。
次の集計パイプラインでは、moviesコレクションを使用して、複数のdimensionsにわたる映画を分類します。A $match stage limits the input to movies with a runtime greater than 1,000 minutes. $facet ステージは、$sortByCount、$bucket、$bucketAuto を使用して 3 つのサブパイプラインを並行して実行します。MongoDB は操作の開始時に 1 回だけ moviesコレクションからinput documentを取得します。
db.movies.aggregate( [ { $match: { runtime: { $gt: 1000 } } }, { $facet: { "categorizedByGenres": [ { $unwind: "$genres" }, { $sortByCount: "$genres" } ], "categorizedByRuntime": [ { $bucket: { groupBy: "$runtime", boundaries: [ 1000, 1200, 1400 ], default: "Other", output: { "count": { $sum: 1 }, "titles": { $push: "$title" } } } } ], "categorizedByYear(Auto)": [ { $bucketAuto: { groupBy: "$year", buckets: 4 } } ] } } ] )
[ { categorizedByGenres: [ { _id: 'Sport', count: 1 }, { _id: 'Documentary', count: 1 }, { _id: 'Action', count: 1 }, { _id: 'Drama', count: 1 }, { _id: 'Adventure', count: 1 }, { _id: 'History', count: 1 } ], categorizedByRuntime: [ { _id: 1000, count: 1, titles: [ 'Baseball' ] }, { _id: 1200, count: 1, titles: [ 'Centennial' ] } ], 'categorizedByYear(Auto)': [ { _id: { min: 1978, max: 1994 }, count: 1 }, { _id: { min: 1994, max: 1994 }, count: 1 } ] } ]
このページのC#の例では、Atlasサンプルデータセット の sample_mflixデータベースを使用します。MongoDB Atlasクラスターを無料で作成して、サンプルデータセットをロードする方法については、 MongoDB .NET/ C#ドライバーのドキュメントの「 開始 」を参照してください。
次の Movie クラスは、sample_mflix.movies コレクション内のドキュメントをモデル化します。
[] public class Movie { [] public ObjectId Id { get; set; } [] public string Title { get; set; } = null!; [] public int? Year { get; set; } [] public int? Runtime { get; set; } [] public string? Rated { get; set; } [] public int Metacritic { get; set; } [] public string? Plot { get; set; } [] public string? Type { get; set; } [] public string[]? Cast { get; set; } [] public string[]? Directors { get; set; } [] public string[]? Writers { get; set; } [] public ImdbData? Imdb { get; set; } }
MongoDB .NET/ C#ドライバーを使用して$facet ステージを集計パイプラインに追加するには、 PipelineDefinitionオブジェクトで ファセット() メソッドを呼び出します。
次の例では、2 つの並列集計を実行するパイプラインステージを作成しています。最初の集計では、受信したドキュメントを、Runtimeフィールドの値により 5 つのグループに分散します。2 番目の集計では、Ratedフィールドの各値をカウントし、各値のカウントを上位 5 つの値に制限して返します。
var bucketPipeline = new EmptyPipelineDefinition<Movie>() .BucketAuto( groupBy: m => m.Runtime, buckets: 5); var bucketFacet = AggregateFacet.Create( name: "Runtimes", pipeline: bucketPipeline); var countLimitPipeline = new EmptyPipelineDefinition<Movie>() .SortByCount(m => m.Rated) .Limit(5); var countFacet = AggregateFacet.Create( "Ratings", countLimitPipeline); var pipeline = new EmptyPipelineDefinition<Movie>() .Facet(bucketFacet, countFacet);
{ "Runtimes": [ { "_id": { "min": null, "max": 89 }, "count": 4574 }, { "_id": { "min": 89, "max": 97 }, "count": 4539 }, { "_id": { "min": 97, "max": 106 }, "count": 4502 }, { "_id": { "min": 106, "max": 121 }, "count": 4421 }, { "_id": { "min": 121, "max": 1256 }, "count": 3313 } ], "Ratings": [ { "_id": null, "count": 9894 }, { "_id": "R", "count": 5537 }, { "_id": "PG-13", "count": 2321 }, { "_id": "PG", "count": 1852 }, { "_id": "APPROVED", "count": 709 } ] }
このページのNode.js の例では、Atlasサンプルデータセット の sample_mflixデータベースを使用します。無料のMongoDB Atlas cluster を作成し、サンプルデータセットをロードする方法については、 MongoDB Node.jsドライバーのドキュメントの開始を参照してください。
MongoDB Node.jsドライバーを使用して $facet ステージを集計パイプラインに追加するには、パイプラインオブジェクトで $facet 演算子を使用します。
次の例では、2 つの並列集計を実行するパイプラインステージを作成しています。最初の集計では、$bucketAuto ステージを使用して、受信したドキュメントを runtimeフィールドの値で 5 つのグループに分散します。2 番目の集計では、ratedフィールドの各値をカウントし、$sortByCount ステージと $limit ステージを使用して上位 5 つの値の数を返します。次に、この例では集計パイプラインを実行します。
const pipeline = [ { $facet: { bucketPipeline: [ { $bucketAuto: { groupBy: "$runtime", buckets: 5 } } ], countLimit: [ { $sortByCount: "$rated" }, { $limit: 5 } ] } } ]; const cursor = collection.aggregate(pipeline); return cursor;
詳細
関連するパイプラインステージの詳細については、$bucketAuto、$sortByCount、および$limitのガイドを参照してください。