ビュー
MongoDB ビューはクエリ可能なオブジェクトであり、その内容は他のコレクションまたはビューの集計パイプラインによって定義されます。 MongoDB はビューの内容をディスクに永続化しません。 ビューのコンテンツは、クライアントがビューをクエリすると、オンデマンドで計算されます。 MongoDB では、クライアントがビューをクエリする権限を持っていることを要求できます。 MongoDB はビューに対する書込み操作をサポートしていません。
例としては次のことができます。
従業員データのコレクションのビューを作成し、
exclude
の個人情報または個人情報(PII)を表示します。 アプリケーションは、 PII を含まない従業員データのビューを照会できます。計算されたフィールドとメトリクスを
add
するには、収集されたセンサーデータのコレクションにビューを作成します。アプリケーションは単純な検索操作を使用してデータをクエリできます。在庫と注文履歴をそれぞれ含む
joins
のビューを作成します。 アプリケーションは、基盤となる複雑なパイプラインを管理したり理解したりしなくても、結合されたデータをクエリできます。
MongoDB Atlas でホストされている配置向け に UI でマテリアライズドビューを作成 できます。
クライアントが ビュー をクエリすると、MongoDB はクライアント クエリを基礎となるパイプラインに追加し、その結合されたパイプラインの結果をクライアントに返します。 MongoDB は、結合されたパイプラインに集計パイプラインの最適化を適用する場合があります。
注意
次のページではビューについて説明します。 オンデマンドのマテリアライズドビューについて詳しくは、「オンデマンドのマテリアライズドビュー 」を参照してください。
ビューの作成
ビューを作成または定義するには、次の手順に従います。
db.createCollection()
メソッドまたはcreate
コマンドを使用します。db.createCollection( "<viewName>", { "viewOn" : "<source>", "pipeline" : [<pipeline>], "collation" : { <collation> } } ) db.createView()
メソッドを使用します。db.createView( "<viewName>", "<source>", [<pipeline>], { "collation" : { <collation> } } )
注意
- ソース コレクションと同じデータベースにビューを作成する必要があります。
警告
MongoDB サーバーがクラッシュするため、 system.profile
という名前の時系列コレクションまたはビューを作成しないでください。
動作
ビューは、次の動作を示します。
読み取り専用
ビューは読み取り専用です。ビューに対する書込み操作はエラーになります。
次の読み取り操作ではビューをサポートできます。
インデックス使用とソート操作
ビューでは、基になるコレクションのインデックスが使用されます。
インデックスは基礎となるコレクションにあるため、ビューでインデックスを直接作成、削除、再構築したり、ビューでインデックスのリストを取得したりすることはできません。
MongoDB 4.4 以降では、ビューで コマンドを実行するときに
$natural
find
の並べ替えを指定できます。MongoDB の以前のバージョンでは、ビューでの$natural
ソートはサポートされていません。ビューの基盤となる集計パイプラインには、ブロッキングソート操作とブロッキンググループ操作のメモリ制限が 100 MB に制限されます。 MongoDB 4.4 以降では、 ビューで
allowDiskUse: true
を使用してfind
コマンドを発行し、MongoDB がブロッキングソートとグループ操作に一時ファイルを使用できるようにします。MongoDB 4.4 より前では、
aggregate
コマンドのみがallowDiskUse
オプションを受け入れていました。
プロジェクションの制限
不変名
ビューの名前を変更することはできません。
ビューの作成
ビューは読み取り操作中にオンデマンドで計算され、MongoDB は基礎となる集計パイプラインの一部としてビューに対して読み取り操作を実行します。 そのため、ビューでは次のような操作はサポートされていません。
ビューの作成に使用される集計パイプラインが
_id
フィールドを抑制している場合、ビュー内のドキュメントには_id
フィールドは表示されません。
ビューをクエリすると、
クエリ
filter
、projection
、sort
、skip
、limit
db.collection.find()
、およびその他の操作は、同等の集計パイプライン ステージに変換されます。変換された集計パイプライン ステージは、ビューの集計パイプラインの末尾に追加されます。 これによって、ビューの作成時に設定されるビューの基礎となるパイプラインは変更されません。
集計パイプライン オプティマイザーは、ビュー集計パイプライン ステージを再形成してパフォーマンスを向上させます。 これによってクエリ結果は変更されません。
シャードビュー
ビューは、基になるコレクションがシャーディングされている場合、シャーディングされたと見なされます。 そのため、 $lookup
操作と$graphLookup
操作ではfrom
フィールドのシャーディングされたビューを指定できません。
ビューと照合
作成時にビューのデフォルトの照合方法を指定できます。照合方法が指定されていない場合、ビューのデフォルトの照合には「単純な」バイナリ比較照合子が使用されます。つまり、ビューはコレクションのデフォルトの照合方法を継承しません。
ビューでの文字列比較では、ビューのデフォルトの照合方法が使用されます。ビューのデフォルトの照合方法を変更または上書きしようとする操作は、エラーとなり、失敗します。
別のビューからビューを作成する場合、ソース ビューの照合方法と異なる照合方法を指定することはできません。
複数のビューが関わる集計(
$lookup
や$graphLookup
など)が実行される場合、それらのビューには同じ照合が含まれる必要があります。
スナップショットの分離
ビューはコレクション変更のタイムスタンプを維持せず、ポイントインタイムまたはスナップショット読み取りの分離をサポートしていません。
パブリックビューの定義
コレクションを一覧表示する操作db.getCollectionInfos()
やdb.getCollectionNames()
など)では、出力にビューが含まれます。
重要
ビュー定義はパブリックです。つまり、ビューに対する db.getCollectionInfos()
および explain
操作には、ビューを定義するパイプラインが含まれます。そのため、ビュー定義で機密性の高いフィールドと値を直接参照することは避けてください。
ビューをドロップする
ビューを削除するには、ビューでdb.collection.drop()
メソッドを使用します。
ビューを変更する
ビューを変更するには、ビューを削除して再作成するか、 collMod
コマンドを使用します。
サポートされている操作
次の操作では、このページに記載されている制限を除き、ビューのサポートを提供します。
コマンド | メソッド |
---|---|
例
次の例で使用するstudents
コレクションを作成します。
db.students.insertMany( [ { sID: 22001, name: "Alex", year: 1, score: 4.0 }, { sID: 21001, name: "bernie", year: 2, score: 3.7 }, { sID: 20010, name: "Chris", year: 3, score: 2.5 }, { sID: 22021, name: "Drew", year: 1, score: 3.2 }, { sID: 17301, name: "harley", year: 6, score: 3.1 }, { sID: 21022, name: "Farmer", year: 1, score: 2.2 }, { sID: 20020, name: "george", year: 3, score: 2.8 }, { sID: 18020, name: "Harley", year: 5, score: 2.8 }, ] )
db.createView() を使用してビューを作成する
db.createView()
を使用して、1 年生に限定したビューを作成します。
db.createView( "firstYears", "students", [ { $match: { year: 1 } } ] )
この例では、次のことが行われます。
firstYears
は、新しいビューの名前です。students
は、ビューの基になっているコレクションです。$match
は、students
コレクション内の 1 年生に一致する集計式です。
この例では、ビューをクエリしています。
db.firstYears.find({}, { _id: 0 } )
以下の出力には、1年生に関するデータを含むドキュメントのみが含まれています。{ _id: 0 }
プロジェクションは、出力内の _id
フィールドを抑制します。
[ { sID: 22001, name: 'Alex', year: 1, score: 4 }, { sID: 22021, name: 'Drew', year: 1, score: 3.2 }, { sID: 21022, name: 'Farmer', year: 1, score: 2.2 } ]
db.createCollection() を使用してビューを作成する
db.createCollection()
メソッドを使用すると、特定のオプションを持つコレクションまたはビューを作成できます。
次の例では、graduateStudents
ビューを作成しています。ビューには、$match
ステージで選択されたドキュメントのみが含まれます。任意の照合設定によって並べ替え順序が決まります。
db.createCollection( "graduateStudents", { viewOn: "students", pipeline: [ { $match: { $expr: { $gt: [ "$year", 4 ] } } } ], collation: { locale: "en", caseFirst: "upper" } } )
次の例では、ビューをクエリします。$unset
ステージでは、わかりやすくするために出力から _id
フィールドが削除されます。
db.graduateStudents.aggregate( [ { $sort: { name: 1 } }, { $unset: [ "_id" ] } ] )
出力がソートされるとき、 $sort
ステージは照合順序を使用して大文字を小文字より先にソートします。
[ { sID: 18020, name: 'Harley', year: 5, score: 2.8 }, { sID: 17301, name: 'harley', year: 6, score: 3.1 } ]
ビューを使用して 2 つのコレクションを結合
多くの場合、 $lookup
を使用して 2 つのコレクションのビューを作成し、そのビューに対してクエリを実行すると便利です。 アプリケーションは、複雑なパイプラインを構築または維持することなく、ビューに対してクエリを実行できます。
inventory
とorders
の 2 つのサンプル コレクションを作成します。
db.inventory.insertMany( [ { prodId: 100, price: 20, quantity: 125 }, { prodId: 101, price: 10, quantity: 234 }, { prodId: 102, price: 15, quantity: 432 }, { prodId: 103, price: 17, quantity: 320 } ] ) db.orders.insertMany( [ { orderID: 201, custid: 301, prodId: 100, numPurchased: 20 }, { orderID: 202, custid: 302, prodId: 101, numPurchased: 10 }, { orderID: 203, custid: 303, prodId: 102, numPurchased: 5 }, { orderID: 204, custid: 303, prodId: 103, numPurchased: 15 }, { orderID: 205, custid: 303, prodId: 103, numPurchased: 20 }, { orderID: 206, custid: 302, prodId: 102, numPurchased: 1 }, { orderID: 207, custid: 302, prodId: 101, numPurchased: 5 }, { orderID: 208, custid: 301, prodId: 100, numPurchased: 10 }, { orderID: 209, custid: 303, prodId: 103, numPurchased: 30 } ] )
各コレクションの要素を組み合わせたビューを作成します。
db.createView( "sales", "orders", [ { $lookup: { from: "inventory", localField: "prodId", foreignField: "prodId", as: "inventoryDocs" } }, { $project: { _id: 0, prodId: 1, orderId: 1, numPurchased: 1, price: "$inventoryDocs.price" } }, { $unwind: "$price" } ] )
この例では、次のことが行われます。
db.createView()
はsales
ビューを作成します。sales
ビューはorders
コレクションに基づいています。$lookup
ステージでは、orders
コレクションのprodId
フィールドを使用して、一致するprodId
フィールドを持つinventory
コレクション内のドキュメントを「結合」します。一致するドキュメントは、
inventoryDocs
フィールドに配列として追加されます。$project
ステージでは、使用可能なフィールドのサブセットが選択されます。$unwind
ステージでは、price
フィールドを配列からスカラー値に変換します。
sales
ビューのドキュメントは以下のとおりです。
{ prodId: 100, numPurchased: 20, price: 20 }, { prodId: 101, numPurchased: 10, price: 10 }, { prodId: 102, numPurchased: 5, price: 15 }, { prodId: 103, numPurchased: 15, price: 17 }, { prodId: 103, numPurchased: 20, price: 17 }, { prodId: 102, numPurchased: 1, price: 15 }, { prodId: 101, numPurchased: 5, price: 10 }, { prodId: 100, numPurchased: 10, price: 20 }, { prodId: 103, numPurchased: 30, price: 17 }
各製品の合計販売金額を見つけるには、ビューをクエリします。
db.sales.aggregate( [ { $group: { _id: "$prodId", amountSold: { $sum: { $multiply: [ "$price", "$numPurchased" ] } } } } ] )
出力は次のとおりです。
[ { _id: 100, amountSold: 600 }, { _id: 103, amountSold: 1105 }, { _id: 101, amountSold: 150 }, { _id: 102, amountSold: 90 } ]