ビューの作成とクエリ
項目一覧
ビューを作成するには、次のいずれかの方法を使用します。
MongoDB Atlas UI でビューを作成するには、マテリアライズドビューを使用する必要があります。詳しくは、「MongoDB Atlas UI でマテリアライズドビューを作成する」を参照してください。
重要
ビュー名はコレクション リスト出力に含まれます
db.getCollectionInfos()
や db.getCollectionNames()
などのコレクションを一覧表示する操作では、出力にビューが含まれます。
ビュー定義はパブリックです。つまり、ビューに対する db.getCollectionInfos()
および explain
操作には、ビューを定義するパイプラインが含まれます。そのため、ビュー定義で機密性の高いフィールドと値を直接参照することは避けてください。
db.createCollection()
構文
db.createCollection( "<viewName>", { "viewOn" : "<source>", "pipeline" : [<pipeline>], "collation" : { <collation> } } )
db.createView()
構文
db.createView( "<viewName>", "<source>", [<pipeline>], { "collation" : { <collation> } } )
制限事項
ソース コレクションと同じデータベースにビューを作成する必要があります。
ビュー定義
pipeline
には、$out
または$merge
ステージを含めることはできません。この制限は、$lookup
ステージまたは$facet
ステージで使用されるパイプラインなどの埋め込みパイプラインにも適用されます。ビューは、一度作成すると名前を変更できません。
サポートされていない操作
一部の操作は、ビューでは使用できません。
$text
演算子(これは、集計の$text
は最初のステージでのみ有効であるためです)。ビューの名前を変更します。
詳しくは、「ビューでサポートされている操作」を参照してください。
例
最初の例では、コレクションに学生データを入力し、データを照会するためのビューを作成しています。
コレクションを入力する
この例で使用する 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" } } )
注意
照合動作
作成時にビューのデフォルトの照合方法を指定できます。照合方法が指定されていない場合、ビューのデフォルトの照合には「単純な」バイナリ比較照合子が使用されます。つまり、ビューはコレクションのデフォルトの照合方法を継承しません。
ビューでの文字列比較では、ビューのデフォルトの照合方法が使用されます。ビューのデフォルトの照合方法を変更または上書きしようとする操作は、エラーとなり、失敗します。
別のビューからビューを作成する場合、ソース ビューの照合方法と異なる照合方法を指定することはできません。
複数のビューが関わる集計(
$lookup
や$graphLookup
など)が実行される場合、それらのビューには同じ照合が含まれる必要があります。
ビューをクエリする
次の例では、ビューをクエリします。$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 } ]
現在のユーザーに付与されたロールの医療情報を取得する
MongoDB 7.0 以降では、新しい USER_ROLES
システム変数を使用してユーザー ロールを返すことができます。
このセクションの例では、医療情報を含むコレクション内のフィールドへのアクセスが制限されているユーザーを示します。この例では、USER_ROLES
システム変数から現在のユーザー ロールを読み取り、ロールに基づいてフィールドを非表示にするビューを使用します。
この例では、次のユーザーを作成します。
James
は、Billing
ロールが付与されており、creditCard
フィールドにアクセスできます。Michelle
は、Provider
ロールが付与されており、diagnosisCode
フィールドにアクセスできます。
ロール、ユーザー、コレクション、ビューを作成するには、次の手順を実行します。
ビューを作成する
システム変数を使用するには、変数名の先頭に $$
を追加します。システム変数 USER_ROLES
を $$USER_ROLES
として指定します。
ビューは、USER_ROLES
システム変数から現在のユーザー ロールを読み取り、ロールに基づいてフィールドを非表示にします。
実行:
db.createView( "medicalView", "medical", [ { $set: { "diagnosisCode": { $cond: { if: { $in: [ "Provider", "$$USER_ROLES.role" ] }, then: "$diagnosisCode", else: "$$REMOVE" } } }, }, { $set: { "creditCard": { $cond: { if: { $in: [ "Billing", "$$USER_ROLES.role" ] }, then: "$creditCard", else: "$$REMOVE" } } } } ] )
ビューの例:
James
がアクセスできる情報を取得するには、次の手順を実行します。
Michelle
がアクセスできる情報を取得するには、次の手順を実行します。
現在のユーザーに付与されたロールの予算ドキュメントを取得する
MongoDB 7.0 以降では、新しい USER_ROLES
システム変数を使用してユーザー ロールを返すことができます。
このセクションのシナリオでは、予算情報を含むコレクション内のドキュメントへのアクセスが制限されているさまざまなロールを持つユーザーを示します。
このシナリオでは、USER_ROLES
の使用法の 1 つを示しています。budget
コレクションには、 allowedRoles
という名前のフィールドを持つドキュメントが含まれています。次のシナリオで示すように、allowedRoles
フィールドにあるユーザー ロールと USER_ROLES
システム変数によって返されるロールを比較するクエリを作成できます。
注意
別のUSER_ROLES
シナリオの例については、「 現在のユーザーに付与されているロールの医療情報の取得」を参照してください。 その例では、次の例とは異なり、ドキュメントフィールドにユーザーロールを保存しません。
このセクションの予算シナリオでは、次の手順を実行してロール、ユーザー、および budget
コレクションを作成します。
ユーザーの作成
必要なロールを持つ John
および Jane
という名前のユーザーを作成します。test
データベースを各自のデータベース名に置き換えてください。
db.createUser( { user: "John", pwd: "jn008", roles: [ { role: "Marketing", db: "test" }, { role: "Development", db: "test" }, { role: "Operations", db: "test" }, { role: "read", db: "test" } ] } ) db.createUser( { user: "Jane", pwd: "je009", roles: [ { role: "Sales", db: "test" }, { role: "Operations", db: "test" }, { role: "read", db: "test" } ] } )
コレクションの作成
実行:
db.budget.insertMany( [ { _id: 0, allowedRoles: [ "Marketing" ], comment: "For marketing team", yearlyBudget: 15000 }, { _id: 1, allowedRoles: [ "Sales" ], comment: "For sales team", yearlyBudget: 17000, salesEventsBudget: 1000 }, { _id: 2, allowedRoles: [ "Operations" ], comment: "For operations team", yearlyBudget: 19000, cloudBudget: 12000 }, { _id: 3, allowedRoles: [ "Development" ], comment: "For development team", yearlyBudget: 27000 } ] )
ビューを作成し、John
がアクセスできるドキュメントを取得するには、次の手順を実行します。
ビューを作成する
システム変数を使用するには、変数名の先頭に $$
を追加します。システム変数 USER_ROLES
を $$USER_ROLES
として指定します。
実行:
db.createView( "budgetView", "budget", [ { $match: { $expr: { $not: { $eq: [ { $setIntersection: [ "$allowedRoles", "$$USER_ROLES.role" ] }, [] ] } } } } ] )
ビューを作成できない場合は、ビューを作成する権限を持つユーザーとしてログインしていることを確認してください。
前の例では、budget
コレクションから、この例を実行するユーザーが持っているロールの少なくとも 1 つと一致するドキュメントが返されます。そのために、この例では $setIntersection
を使用して、 budget
ドキュメントの allowedRoles
フィールドと $$USER_ROLES
のユーザー ロールのセットの共通部分が空ではないドキュメントを返します。
ドキュメントを確認します。
John
Marketing
、 Operations
、そして Development
ロールを有するかを確認し、次のドキュメントを参照します。
[ { _id: 0, allowedRoles: [ 'Marketing' ], comment: 'For marketing team', yearlyBudget: 15000 }, { _id: 2, allowedRoles: [ 'Operations' ], comment: 'For operations team', yearlyBudget: 19000, cloudBudget: 12000 }, { _id: 3, allowedRoles: [ 'Development' ], comment: 'For development team', yearlyBudget: 27000 } ]
Jane がアクセスできるドキュメントを取得するには、次の手順を実行します。
ドキュメントを確認します。
Jane
は Sales
と Operations
のロールを持ち、次のドキュメントを参照します。
[ { _id: 1, allowedRoles: [ 'Sales' ], comment: 'For sales team', yearlyBudget: 17000, salesEventsBudget: 1000 }, { _id: 2, allowedRoles: [ 'Operations' ], comment: 'For operations team', yearlyBudget: 19000, cloudBudget: 12000 } ]
注意
シャーディングされたクラスターでは、ユーザーに代わって別のサーバーノードがシャード上でクエリを実行できます。これらのクエリでは、USER_ROLES
には引き続きユーザーのロールが使用されます。
複数のデータベースで同じ名前のロール
複数のデータベースに同じ名前のロールが存在する場合があります。ビューを作成し、ビュー内の特定のロール参照する場合は、db
データベース名フィールドと role
フィールドの両方を指定するか、データベース名とロールを含む _id
フィールドを指定する必要があります。
次の例では、異なる名前のロールを持つ Jane
に割り当てられたロールを返します。この例では、_id
、role
、および db
のデータベース名が返されます。
動作
次のセクションでは、ビューの作成とクエリの動作について説明します。
集計の最適化
ビューをクエリする場合:
クエリ
filter
、projection
、sort
、skip
、limit
db.collection.find()
、およびその他の操作は、同等の集計パイプライン ステージに変換されます。MongoDB は、クライアント クエリを基礎となるパイプラインに追加し、その結合されたパイプラインの結果をクライアントに返します。MongoDB は、結合されたパイプラインに 集計パイプラインの最適化を適用する場合があります。
集計パイプライン オプティマイザーは、ビュー集計パイプライン ステージを再形成してパフォーマンスを向上させます。最適化によってクエリ結果は変更されません。
リソースのロック
db.createView()
は、操作中、指定されたコレクションまたはビューに対する排他ロックを取得します。コレクションに対する後続のすべての操作は、db.createView()
がロックを解放するまで待機する必要があります。db.createView()
は通常、このロックを短時間保持します。
ビューを作成するには、データベース内の system.views
コレクションに対する追加の排他ロックを取得する必要があります。このロックは、コマンドが完了するまでデータベース内のビューの作成または変更をブロックします。