Docs Menu
Docs Home
/
MongoDBマニュアル
/ /

オンデマンドのマテリアライズドビュー

項目一覧

  • 標準ビューとの比較
  • MongoDB Atlas UI でマテリアライズド ビューを作成する
  • 詳細情報

注意

曖昧さ回避

このページでは、オンデマンド マテリアライズドビューについて説明します。標準ビューについて詳しくは、「 ビュー」をご覧ください。

ビュータイプの違いを理解するには、「 標準ビューとの比較 」を参照してください。

オンデマンドのマテリアライズドビューは、事前に計算された集計パイプラインの結果で、ディスクに保存され、ディスクから読み取られます。オンデマンドのマテリアライズドビューは通常、 $merge 、または$outステージの結果です。

MongoDB には、 標準ビューオンデマンドのマテリアライズドビューの 2 つの異なるビュータイプがあります。どちらのビュー タイプも、集計パイプラインから結果を返します。

  • 標準ビューはビューを読み取るときに計算され、ディスクに保存されません。

  • オンデマンドのマテリアライズドビューはディスクに保存され、ディスクから読み取れます。保存されたデータをアップデートするために、$mergeまたは$outステージを使用します。

    注意

    $mergeを使用すると、変更ストリームを使用してマテリアライズドビューの変更を監視できます。 $outを使用している場合、マテリアライズドビューの変更を監視することはできません。

標準ビューでは、基になるコレクションのインデックスが使用されます。そのため、標準ビューでインデックスを直接作成、削除、再構築したり、ビューでインデックスのリストを取得したりすることはできません。

オンデマンドのマテリアライズドビューはディスクに保存されるため、インデックスを直接作成できます。

オンデマンドのマテリアライズドビューは、クエリの一部として計算されるのではなくディスクから読み取られるため、標準ビューよりも読み取りパフォーマンスが向上します。このパフォーマンス上の利点は、パイプラインの複雑さと集約されるデータのサイズに応じて大きくなります。

このセクションの例では、映画データセットのサンプルを使用します。サンプル データセットを MongoDB Atlas 配置にロードする方法について詳しくは、「サンプル データのロード」を参照してください。

MongoDB Atlas UI でマテリアライズドビューを作成するには、次の手順に従います。

1
  1. まだ表示されていない場合は、希望するプロジェクトを含む組織を選択しますナビゲーション バーのOrganizationsメニュー

  2. まだ表示されていない場合は、ナビゲーション バーの Projects メニューからプロジェクトを選択します。

  3. まだ表示されていない場合は、サイドバーの [Clusters] をクリックします。

    [ Clusters (クラスター) ] ページが表示されます。

2
  1. サンプル データを含むクラスターで、[ Browse Collections ] をクリックします。

  2. 左側のナビゲーション ペインで、sample_training データベースを選択します。

  3. grades コレクションを選択します。

4
5

集計ステージでは、ビューとして保存するデータが変換されます。利用可能な集計ステージの詳細については、「集計ステージ」を参照してください。

この例では、 $set ステージで新しいフィールドを追加しています。

  1. Selectドロップダウン メニューから [$set] を選択します。

  2. 次の構文を集計パイプラインエディターに追加して、grades コレクション内の scores 配列のすべての score 値の平均スコアを作成します。

    {
    averageScore: { $avg: "$scores.score" }
    }

    MongoDB Atlas は各ドキュメントにaverageScore値を追加します。

6
7
  1. Selectドロップダウン メニューから $out ステージを選択します。

  2. 集約パイプラインに次の構文を追加して、パイプラインの結果を sample_training データベースの myView コレクションに書き込みます。

    'myView'
  3. [Save Documents] をクリックします。

$out ステージでは、集計パイプラインの結果を指定されたコレクションが書き込まれ、ビューが作成されます。詳細については、 $outを参照してください。

myViewコレクションを表示するには、コレクションのリストを更新してください。

MongoDB Atlas UI でmyViewコレクションをクエリする方法については、MongoDB Atlas ドキュメントの「ドキュメントの表示、フィルタリング、ソート 」を参照してください。

2019 年 1 月の終わり頃に、コレクション「bakesales」にはアイテム別の売上情報が含まれていると仮定します。

db.bakesales.insertMany( [
{ date: new ISODate("2018-12-01"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
{ date: new ISODate("2018-12-02"), item: "Cake - Peanut Butter", quantity: 5, amount: new NumberDecimal("90") },
{ date: new ISODate("2018-12-02"), item: "Cake - Red Velvet", quantity: 10, amount: new NumberDecimal("200") },
{ date: new ISODate("2018-12-04"), item: "Cookies - Chocolate Chip", quantity: 20, amount: new NumberDecimal("80") },
{ date: new ISODate("2018-12-04"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
{ date: new ISODate("2018-12-05"), item: "Pie - Key Lime", quantity: 3, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-01-25"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-01-25"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
{ date: new ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-01-26"), item: "Cookies - Chocolate Chip", quantity: 12, amount: new NumberDecimal("48") },
{ date: new ISODate("2019-01-26"), item: "Cake - Carrot", quantity: 2, amount: new NumberDecimal("36") },
{ date: new ISODate("2019-01-26"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-01-27"), item: "Pie - Chocolate Cream", quantity: 1, amount: new NumberDecimal("20") },
{ date: new ISODate("2019-01-27"), item: "Cake - Peanut Butter", quantity: 5, amount: new NumberDecimal("80") },
{ date: new ISODate("2019-01-27"), item: "Tarts - Apple", quantity: 3, amount: new NumberDecimal("12") },
{ date: new ISODate("2019-01-27"), item: "Cookies - Chocolate Chip", quantity: 12, amount: new NumberDecimal("48") },
{ date: new ISODate("2019-01-27"), item: "Cake - Carrot", quantity: 5, amount: new NumberDecimal("36") },
{ date: new ISODate("2019-01-27"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-01-28"), item: "Cookies - Chocolate Chip", quantity: 20, amount: new NumberDecimal("80") },
{ date: new ISODate("2019-01-28"), item: "Pie - Key Lime", quantity: 3, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-01-28"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
] );

次の updateMonthlySales 関数は、累積月間売上情報を含む monthlybakesales マテリアライズドビューを定義します。この例では、関数は日付パラメーターを受け取り、特定の日付から始まる月間売上情報のみが更新されています。

updateMonthlySales = function(startDate) {
db.bakesales.aggregate( [
{ $match: { date: { $gte: startDate } } },
{ $group: { _id: { $dateToString: { format: "%Y-%m", date: "$date" } }, sales_quantity: { $sum: "$quantity"}, sales_amount: { $sum: "$amount" } } },
{ $merge: { into: "monthlybakesales", whenMatched: "replace" } }
] );
};
  • $matchステージでは、データがフィルタリングされ、 startDate以上の売上のみが処理されます。

  • $groupステージでは、売上情報が年月別にグループ化されます。このステージで出力されるドキュメントは、以下のような形式になります。

    { "_id" : "<YYYY-mm>", "sales_quantity" : <num>, "sales_amount" : <NumberDecimal> }
  • $merge ステージは出力を monthlybakesales コレクションに書き込みます。

    このステージでは、_idフィールド(シャーディングされていないコレクションのデフォルト)基づいて、集計結果内のドキュメントがコレクション内の既存のドキュメントと一致するかどうかが確認されます。

最初の実行では、new ISODate("1970-01-01") の日付を渡すことができます。

updateMonthlySales(new ISODate("1970-01-01"));

最初の実行後、monthlybakesales には次のドキュメントが含まれます。つまり、db.monthlybakesales.find().sort( { _id: 1 } ) は次を返します。

{ "_id" : "2018-12", "sales_quantity" : 41, "sales_amount" : NumberDecimal("506") }
{ "_id" : "2019-01", "sales_quantity" : 86, "sales_amount" : NumberDecimal("896") }

2019 年 2 月の第 1 週までに、bakesales コレクションが新しい販売情報、具体的には 1 月と 2 月の追加販売でアップデートされる予定です。

db.bakesales.insertMany( [
{ date: new ISODate("2019-01-28"), item: "Cake - Chocolate", quantity: 3, amount: new NumberDecimal("90") },
{ date: new ISODate("2019-01-28"), item: "Cake - Peanut Butter", quantity: 2, amount: new NumberDecimal("32") },
{ date: new ISODate("2019-01-30"), item: "Cake - Red Velvet", quantity: 1, amount: new NumberDecimal("20") },
{ date: new ISODate("2019-01-30"), item: "Cookies - Chocolate Chip", quantity: 6, amount: new NumberDecimal("24") },
{ date: new ISODate("2019-01-31"), item: "Pie - Key Lime", quantity: 2, amount: new NumberDecimal("40") },
{ date: new ISODate("2019-01-31"), item: "Pie - Banana Cream", quantity: 2, amount: new NumberDecimal("40") },
{ date: new ISODate("2019-02-01"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") },
{ date: new ISODate("2019-02-01"), item: "Tarts - Apple", quantity: 2, amount: new NumberDecimal("8") },
{ date: new ISODate("2019-02-02"), item: "Cake - Chocolate", quantity: 2, amount: new NumberDecimal("60") },
{ date: new ISODate("2019-02-02"), item: "Cake - Peanut Butter", quantity: 1, amount: new NumberDecimal("16") },
{ date: new ISODate("2019-02-03"), item: "Cake - Red Velvet", quantity: 5, amount: new NumberDecimal("100") }
] )

1 月と 2 月の monthlybakesales データをアップデートするには、関数を再度実行して、new ISODate("2019-01-01") から集計パイプラインを再実行します。

updateMonthlySales(new ISODate("2019-01-01"));

monthlybakesales のコンテンツは、bakesales コレクションの最新データを反映するようにアップデートされました。つまり、db.monthlybakesales.find().sort( { _id: 1 } ) は以下を返します。

{ "_id" : "2018-12", "sales_quantity" : 41, "sales_amount" : NumberDecimal("506") }
{ "_id" : "2019-01", "sales_quantity" : 102, "sales_amount" : NumberDecimal("1142") }
{ "_id" : "2019-02", "sales_quantity" : 15, "sales_amount" : NumberDecimal("284") }

$merge段階:

  • 同じデータベースまたは異なるデータベース内のコレクションに出力できます。

  • 出力コレクションがまだ存在しない場合は、新しいコレクションを作成します。

  • 結果(新しいドキュメントの挿入、ドキュメントのマージ、ドキュメントの置換、既存のドキュメントの保持、操作の失敗、カスタムアップデートパイプラインによるドキュメントの処理)を既存のコレクションに組み込むことができます。

  • シャーディングされたコレクションに出力できます。入力コレクションもシャーディング可能です。

以下については、$mergeを参照してください:

戻る

サポートされている操作