定義
- $facet
- 同じ入力ドキュメントセット上の単一ステージ内の複数の 集計パイプラインを処理します。各サブパイプラインには出力ドキュメントに独自のフィールドがあり、その結果はドキュメントの配列として保存されます。 - $facetステージでは、1 つの集計ステージ内で複数のディメンションまたはファセットにわたるデータを特徴付ける多面的な集計を作成できます。ファセット集計により、データの参照と分析をガイドする複数のフィルターと分類が提供されます。小売業者は通常、商品の価格、メーカー、サイズなどのフィルターを作成して検索結果を絞り込むためにファセットを使用します。- 入力ドキュメントは - $facetステージに一度だけ渡されます。- $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 をトリガーしません。
最適化の提案については、「集計パイプラインの最適化」を参照してください。
例
在庫が次のartworkコレクションに保存されているオンライン ストアを考えてみましょう。
{ "_id" : 1, "title" : "The Pillars of Society", "artist" : "Grosz", "year" : 1926,   "price" : Decimal128("199.99"),   "tags" : [ "painting", "satire", "Expressionism", "caricature" ] } { "_id" : 2, "title" : "Melancholy III", "artist" : "Munch", "year" : 1902,   "price" : Decimal128("280.00"),   "tags" : [ "woodcut", "Expressionism" ] } { "_id" : 3, "title" : "Dancer", "artist" : "Miro", "year" : 1925,   "price" : Decimal128("76.04"),   "tags" : [ "oil", "Surrealism", "painting" ] } { "_id" : 4, "title" : "The Great Wave off Kanagawa", "artist" : "Hokusai",   "price" : Decimal128("167.30"),   "tags" : [ "woodblock", "ukiyo-e" ] } { "_id" : 5, "title" : "The Persistence of Memory", "artist" : "Dali", "year" : 1931,   "price" : Decimal128("483.00"),   "tags" : [ "Surrealism", "painting", "oil" ] } { "_id" : 6, "title" : "Composition VII", "artist" : "Kandinsky", "year" : 1913,  "price" : Decimal128("385.00"),   "tags" : [ "oil", "painting", "abstract" ] } { "_id" : 7, "title" : "The Scream", "artist" : "Munch", "year" : 1893,   "tags" : [ "Expressionism", "painting", "oil" ] } { "_id" : 8, "title" : "Blue Flower", "artist" : "O'Keefe", "year" : 1918,   "price" : Decimal128("118.42"),   "tags" : [ "abstract", "painting" ] } 
次のオペレーションでは、MongoDB のファセット機能を使用して、タグ、価格、作成年などの複数のディメンションで分類されたストアの在庫を顧客に提供します。この$facetステージには、この多面的な集計を実行するために$sortByCount 、 $bucket 、または$bucketAutoを使用する 3 つのサブパイプラインがあります。 artworkからの入力ドキュメントは、操作の開始時にデータベースから 1 回だけ取得されます。
db.artwork.aggregate( [  {    $facet: {      "categorizedByTags": [        { $unwind: "$tags" },        { $sortByCount: "$tags" }      ],      "categorizedByPrice": [        // Filter out documents without a price e.g., _id: 7        { $match: { price: { $exists: 1 } } },        {          $bucket: {            groupBy: "$price",            boundaries: [  0, 150, 200, 300, 400 ],            default: "Other",            output: {              "count": { $sum: 1 },              "titles": { $push: "$title" }            }          }        }      ],      "categorizedByYears(Auto)": [        {          $bucketAuto: {            groupBy: "$year",            buckets: 4          }        }      ]    }  } ]) 
この操作を実行すると次のドキュメントが返されます。
{  "categorizedByYears(Auto)" : [    // First bucket includes the document without a year, e.g., _id: 4    { "_id" : { "min" : null, "max" : 1902 }, "count" : 2 },    { "_id" : { "min" : 1902, "max" : 1918 }, "count" : 2 },    { "_id" : { "min" : 1918, "max" : 1926 }, "count" : 2 },    { "_id" : { "min" : 1926, "max" : 1931 }, "count" : 2 }  ],  "categorizedByPrice" : [    {      "_id" : 0,      "count" : 2,      "titles" : [        "Dancer",        "Blue Flower"      ]    },    {      "_id" : 150,      "count" : 2,      "titles" : [        "The Pillars of Society",        "The Great Wave off Kanagawa"      ]    },    {      "_id" : 200,      "count" : 1,      "titles" : [        "Melancholy III"      ]    },    {      "_id" : 300,      "count" : 1,      "titles" : [        "Composition VII"      ]    },    {      // Includes document price outside of bucket boundaries, e.g., _id: 5      "_id" : "Other",      "count" : 1,      "titles" : [        "The Persistence of Memory"      ]    }  ],  "categorizedByTags" : [    { "_id" : "painting", "count" : 6 },    { "_id" : "oil", "count" : 4 },    { "_id" : "Expressionism", "count" : 3 },    { "_id" : "Surrealism", "count" : 2 },    { "_id" : "abstract", "count" : 2 },    { "_id" : "woodblock", "count" : 1 },    { "_id" : "woodcut", "count" : 1 },    { "_id" : "ukiyo-e", "count" : 1 },    { "_id" : "satire", "count" : 1 },    { "_id" : "caricature", "count" : 1 }  ] } 
このページの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; }         []     public DateTime LastUpdated { get; set; } } 
注意
パスカルケースの ConventionPack
このページのC# クラスはプロパティ名にパスカルケースを使用していますが、MongoDB コレクションのフィールド名はキャメルケースを使用しています。この違いを考慮するために、アプリケーションが起動する際に次のコードを使用してConventionPackを登録してください。
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true); 
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); 
このページの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のガイドを参照してください。