ANNOUNCEMENT: Voyage AI joins MongoDB to power more accurate and trustworthy AI applications on Atlas.
Learn more
Docs Menu

ビューの作成とクエリ

ビューを作成するには、次のいずれかの方法を使用します。

MongoDB Atlas UI でビューを作成するには、マテリアライズドビューを使用する必要があります。詳しくは、「MongoDB Atlas UI でマテリアライズドビューを作成する」を参照してください。

重要

ビュー名はコレクション リスト出力に含まれます

db.getCollectionInfos()db.getCollectionNames() などのコレクションを一覧表示する操作では、出力にビューが含まれます。

ビュー定義はパブリックです。つまり、ビューに対する db.getCollectionInfos() および explain操作には、ビューを定義するパイプラインが含まれます。そのため、ビュー定義で機密性の高いフィールドと値を直接参照することは避けてください。

db.createCollection(
"<viewName>",
{
"viewOn" : "<source>",
"pipeline" : [<pipeline>],
"collation" : { <collation> }
}
)
db.createView(
"<viewName>",
"<source>",
[<pipeline>],
{
"collation" : { <collation> }
}
)
  • ソース コレクションと同じデータベースにビューを作成する必要があります。

  • ビュー定義pipelineには、$outまたは$mergeステージを含めることはできません。この制限は、$lookupステージまたは$facetステージで使用されるパイプラインなどの埋め込みパイプラインにも適用されます。

  • ビューは、一度作成すると名前を変更できません。

一部の操作は、ビューでは使用できません。

  • db.collection.mapReduce().

  • $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() を使用して、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 }
]

注意

プロジェクションの制限

ビューに対するfind()操作では、次のクエリ 演算子およびプロジェクション 演算子をサポートしていません。

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 フィールドにアクセスできます。

ロール、ユーザー、コレクション、ビューを作成するには、次の手順を実行します。

1

実行:

db.createRole( { role: "Billing", privileges: [ { resource: { db: "test",
collection: "medicalView" }, actions: [ "find" ] } ], roles: [ ] } )
db.createRole( { role: "Provider", privileges: [ { resource: { db: "test",
collection: "medicalView" }, actions: [ "find" ] } ], roles: [ ] } )
2

必要なロールを持つ James および Michelle という名前のユーザーを作成します。test データベースを各自のデータベース名に置き換えてください。

db.createUser( {
user: "James",
pwd: "js008",
roles: [
{ role: "Billing", db: "test" }
]
} )
db.createUser( {
user: "Michelle",
pwd: "me009",
roles: [
{ role: "Provider", db: "test" }
]
} )
3

実行:

db.medical.insertMany( [
{
_id: 0,
patientName: "Jack Jones",
diagnosisCode: "CAS 17",
creditCard: "1234-5678-9012-3456"
},
{
_id: 1,
patientName: "Mary Smith",
diagnosisCode: "ACH 01",
creditCard: "6541-7534-9637-3456"
}
] )
4

システム変数を使用するには、変数名の先頭に $ を追加します。システム変数 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"
}
}
}
} ]
)

ビューの例:

  • には、Providerロールを持つユーザーの diagnosisCode フィールドが含まれます。

  • には、Billingロールを持つユーザーの creditCard フィールドが含まれます。

  • $set パイプライン ステージと $REMOVE を使用して、ビューをクエリするユーザーが $USER_ROLES.role で返される一致するロールを持っているかどうかに基づいてフィールドを非表示にします。

James がアクセスできる情報を取得するには、次の手順を実行します。

1

実行:

db.auth( "James", "js008" )
2

実行:

db.medicalView.find()
3

James には Billing ロールが付与され、creditCard フィールドは含まれるが diagnosisCode フィールドは含まれない次のドキュメントを確認できます。

[
{
_id: 0, patientName: 'Jack Jones',
creditCard: '1234-5678-9012-3456'
},
{
_id: 1, patientName: 'Mary Smith',
creditCard: '6541-7534-9637-3456'
}
]

Michelle がアクセスできる情報を取得するには、次の手順を実行します。

1

実行:

db.auth( "Michelle", "me009" )
2

実行:

db.medicalView.find()
3

Michelle には Provider ロールが付与され、diagnosisCode フィールドは含まれるが creditCard フィールドは含まれない次のドキュメントを確認できます。

[
{ _id: 0, patientName: 'Jack Jones',
diagnosisCode: 'CAS 17' },
{ _id: 1, patientName: 'Mary Smith',
diagnosisCode: 'ACH 01' }
]

MongoDB 7.0 以降では、新しい USER_ROLES システム変数を使用してユーザー ロールを返すことができます。

このセクションのシナリオでは、予算情報を含むコレクション内のドキュメントへのアクセスが制限されているさまざまなロールを持つユーザーを示します。

このシナリオでは、USER_ROLES の使用法の 1 つを示しています。budget コレクションには、 allowedRoles という名前のフィールドを持つドキュメントが含まれています。次のシナリオで示すように、allowedRoles フィールドにあるユーザー ロールと USER_ROLES システム変数によって返されるロールを比較するクエリを作成できます。

注意

別の USER_ROLES シナリオの例については、「現在のユーザーに付与されているロールの医療情報の取得」を参照してください。その例では、次の例とは異なり、ドキュメントフィールドにユーザーロールを保存していません。

このセクションの予算シナリオでは、次の手順を実行してロール、ユーザー、および budget コレクションを作成します。

1

実行:

db.createRole( { role: "Marketing", roles: [], privileges: [] } )
db.createRole( { role: "Sales", roles: [], privileges: [] } )
db.createRole( { role: "Development", roles: [], privileges: [] } )
db.createRole( { role: "Operations", roles: [], privileges: [] } )
2

必要なロールを持つ 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" }
]
} )
3

実行:

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 がアクセスできるドキュメントを取得するには、次の手順を実行します。

1

システム変数を使用するには、変数名の先頭に $ を追加します。システム変数 USER_ROLES$USER_ROLES として指定します。

実行:

db.createView(
"budgetView", "budget",
[ {
$match: {
$expr: {
$not: {
$eq: [ { $setIntersection: [ "$allowedRoles", "$$USER_ROLES.role" ] }, [] ]
}
}
}
} ]
)

ビューを作成できない場合は、ビューを作成する権限を持つユーザーとしてログインしていることを確認してください。

前の例では、budget コレクションから、この例を実行するユーザーが持っているロールの少なくとも 1 つと一致するドキュメントが返されます。そのために、この例では $setIntersection を使用して、 budget ドキュメントの allowedRoles フィールドと $USER_ROLES のユーザー ロールのセットの共通部分が空ではないドキュメントを返します。

2

実行:

db.auth( "John", "jn008" )
3

実行:

db.budgetView.find()
4

John は、MarketingOperationsDevelopment のロールを持ち、次のドキュメントを参照します。

[
{
_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 がアクセスできるドキュメントを取得するには、次の手順を実行します。

1

実行:

db.auth( "Jane", "je009" )
2

実行:

db.budgetView.find()
3

JaneSalesOperations のロールを持ち、次のドキュメントを参照します。

[
{
_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 に割り当てられたロールを返します。この例では、_idrole、および db のデータベース名が返されます。

1

実行:

db.auth( "Jane", "je009" )
2

実行:

db.budget.findOne( {}, { myRoles: "$$USER_ROLES" } )
3

myRoles 配列内の _idrole、および db データベース名が表示される出力例。

{
_id: 0,
myRoles: [
{ _id: 'test.Operations', role: 'Operations', db: 'test' },
{ _id: 'test.Sales', role: 'Sales', db: 'test' },
{ _id: 'test.read', role: 'read', db: 'test' }
]
}

次のセクションでは、ビューの作成とクエリの動作について説明します。

ビューをクエリする場合:

  • クエリ filterprojectionsortskiplimitdb.collection.find()、およびその他の操作は、同等の集計パイプライン ステージに変換されます。

  • MongoDB は、クライアント クエリを基礎となるパイプラインに追加し、その結合されたパイプラインの結果をクライアントに返します。MongoDB は、結合されたパイプラインに 集計パイプラインの最適化を適用する場合があります。

  • 集計パイプライン オプティマイザーは、ビュー集計パイプライン ステージを再形成してパフォーマンスを向上させます。最適化によってクエリ結果は変更されません。

db.createView() は、操作中、指定されたコレクションまたはビューに対する排他ロックを取得します。コレクションに対する後続のすべての操作は、db.createView() がロックを解放するまで待機する必要があります。db.createView() は通常、このロックを短時間保持します。

ビューを作成するには、データベース内の system.views コレクションに対する追加の排他ロックを取得する必要があります。このロックは、コマンドが完了するまでデータベース内のビューの作成または変更をブロックします。