オンデマンドのマテリアライズドビュー
注意
曖昧さ回避
このページでは、オンデマンド マテリアライズドビューについて説明します。標準ビューについて詳しくは、「 ビュー」をご覧ください。
ビュータイプの違いを理解するには、「 標準ビューとの比較 」を参照してください。
オンデマンドのマテリアライズドビューは、事前に計算された集計パイプラインの結果で、ディスクに保存され、ディスクから読み取られます。オンデマンドのマテリアライズドビューは通常、 $merge
、または$out
ステージの結果です。
標準ビューとの比較
MongoDB には、 標準ビュー と オンデマンドのマテリアライズドビューの 2 つの異なるビュータイプがあります。どちらのビュー タイプも、集計パイプラインから結果を返します。
標準ビューはビューを読み取るときに計算され、ディスクに保存されません。
オンデマンドのマテリアライズドビューはディスクに保存され、ディスクから読み取れます。保存されたデータをアップデートするために、
$merge
または$out
ステージを使用します。
Indexes
標準ビューでは、基になるコレクションのインデックスが使用されます。そのため、標準ビューでインデックスを直接作成、削除、再構築したり、ビューでインデックスのリストを取得したりすることはできません。
オンデマンドのマテリアライズドビューはディスクに保存されるため、インデックスを直接作成できます。
パフォーマンス
オンデマンドのマテリアライズドビューは、クエリの一部として計算されるのではなくディスクから読み取られるため、標準ビューよりも読み取りパフォーマンスが向上します。このパフォーマンス上の利点は、パイプラインの複雑さと集約されるデータのサイズに応じて大きくなります。
MongoDB Atlas UI でマテリアライズド ビューを作成する
このセクションの例では、訓練用サンプル データセットを使用します。サンプル データセットを MongoDB Atlas 配置にロードする方法について詳しくは、「サンプル データのロード」を参照してください。
MongoDB Atlas UI でマテリアライズドビューを作成するには、次の手順に従います。
MongoDB Atlas UI で、プロジェクトの Clusters ページに移動します。
警告
ナビゲーションの改善が進行中
現在、新しく改善されたナビゲーション エクスペリエンスを展開しています。次の手順が Atlas UIのビューと一致しない場合は、Atlas のプレビュー ドキュメントを参照してください。
まだ表示されていない場合は、希望するプロジェクトを含む組織を選択しますナビゲーション バーのOrganizationsメニュー
まだ表示されていない場合は、ナビゲーション バーの Projects メニューからプロジェクトを選択します。
まだ表示されていない場合は、サイドバーの [Clusters] をクリックします。
[ Clusters (クラスター) ] ページが表示されます。
[0} ] タブをクリックしますAggregation
ドロップダウン メニューから集計ステージを選択しますSelect
集計ステージでは、ビューとして保存するデータが変換されます。利用可能な集計ステージの詳細については、「集計ステージ」を参照してください。
この例では、 $set
ステージで新しいフィールドを追加しています。
Selectドロップダウン メニューから [
$set
] を選択します。次の構文を集計パイプラインエディターに追加して、
grades
コレクション内のscores
配列のすべてのscore
値の平均スコアを作成します。{ averageScore: { $avg: "$scores.score" } } MongoDB Atlas は各ドキュメントに
averageScore
値を追加します。
ステージを追加します$out
Selectドロップダウン メニューから
$out
ステージを選択します。集約パイプラインに次の構文を追加して、パイプラインの結果を
sample_training
データベースのmyView
コレクションに書き込みます。'myView' [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") }, ] );
1. オンデマンドのマテリアライズドビューを定義する
次の 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
フィールド(シャーディングされていないコレクションのデフォルト)に基づいて、集計結果内のドキュメントがコレクション内の既存のドキュメントと一致するかどうかが確認されます。一致がある場合(つまり、同じ年月を持つドキュメントがコレクション内に既に存在する場合)、このステージは既存のドキュメントが集計結果のドキュメントに置き換えられます。
一致しない場合、ステージは集計結果からドキュメントをコレクションに挿入します(一致しない場合のデフォルトの動作)。
2. 初期実行の実行
最初の実行では、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") }
3. マテリアライズドビューのアップデート
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
を参照してください:
$merge
と利用可能なオプションに関する詳細情報