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

ビュー

項目一覧

  • ビューの作成
  • 動作
  • ビューをドロップする
  • ビューを変更する
  • サポートされている操作

MongoDB ビューはクエリ可能なオブジェクトであり、その内容は他のコレクションまたはビューの集計パイプラインによって定義されます。 MongoDB はビューの内容をディスクに永続化しません。 ビューのコンテンツは、クライアントがビューをクエリすると、オンデマンドで計算されます。 MongoDB では、クライアントがビューをクエリする権限を持っていることを要求できます。 MongoDB はビューに対する書込み操作をサポートしていません。

例としては次のことができます。

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

注意

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

ビューを作成または定義するには、次の手順に従います。

  • db.createCollection()メソッドまたはcreateコマンドを使用します。

    db.createCollection(
    "<viewName>",
    {
    "viewOn" : "<source>",
    "pipeline" : [<pipeline>],
    "collation" : { <collation> }
    }
    )
  • db.createView()メソッドを使用します。

    db.createView(
    "<viewName>",
    "<source>",
    [<pipeline>],
    {
    "collation" : { <collation> }
    }
    )

注意

- ソース コレクションと同じデータベースにビューを作成する必要があります。

  • ビュー定義pipelineには$outまたは$mergeステージを含めることはできません。 ビュー定義にネストされたパイプラインが含まれている場合(たとえば、ビュー定義に$lookupまたは$facetステージが含まれている場合)、この制限はネストされたパイプラインにも適用されます。

警告

MongoDB サーバーがクラッシュするため、 system.profileという名前の時系列コレクションまたはビューを作成しないでください。

ビューは、次の動作を示します。

ビューは読み取り専用です。ビューに対する書込み操作はエラーになります。

次の読み取り操作ではビューをサポートできます。

  • ビューでは、基になるコレクションのインデックスが使用されます。

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

  • MongoDB 4.4 以降では、ビューで コマンドを実行するときに$natural findの並べ替えを指定できます。MongoDB の以前のバージョンでは、ビューでの$naturalソートはサポートされていません。

  • ビューの基盤となる集計パイプラインには、ブロッキングソート操作とブロッキンググループ操作のメモリ制限が 100 MB に制限されます。 MongoDB 4.4 以降では、 ビューでallowDiskUse: trueを使用してfindコマンドを発行し、MongoDB がブロッキングソートとグループ操作に一時ファイルを使用できるようにします。

    MongoDB 4.4 より前では、 aggregateコマンドのみがallowDiskUseオプションを受け入れていました。

    Tip

    以下も参照してください。

    ブロッキングソート操作のメモリ制限の詳細については、「ソート操作 」を参照してください。

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

ビューの名前を変更することはできません。

  • ビューは読み取り操作中にオンデマンドで計算され、MongoDB は基礎となる集計パイプラインの一部としてビューに対して読み取り操作を実行します。 そのため、ビューでは次のような操作はサポートされていません。

  • ビューの作成に使用される集計パイプラインが_idフィールドを抑制している場合、ビュー内のドキュメントには_idフィールドは表示されません。

ビューをクエリすると、

  • クエリ filterprojectionsortskiplimit 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() を使用して、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() メソッドを使用すると、特定のオプションを持つコレクションまたはビューを作成できます。

次の例では、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 }
]

多くの場合、 $lookupを使用して 2 つのコレクションのビューを作成し、そのビューに対してクエリを実行すると便利です。 アプリケーションは、複雑なパイプラインを構築または維持することなく、ビューに対してクエリを実行できます。

inventoryorders の 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 }
]

戻る

データベースとコレクション