メインコンテンツにスキップ

ビュー

警告

ビューのサポートは現在、非常に初期のプレビュー機能です。viewキーワードを使用してビューをPrismaスキーマに追加したり、db pullでデータベーススキーマのビューをイントロスペクトしたりできます。--create-onlyフラグを使用して変更を移行ファイルに手動で追加しない限り、Prisma Migrateとdb pushを使用してスキーマ内のビューをデータベースに適用することはまだできません。

この機能の進捗状況の更新については、GitHub issueをフォローしてください。

データベースビューを使用すると、クエリに名前を付けて保存できます。リレーショナルデータベースでは、ビューは保存されたSQLクエリであり、複数のテーブルの列や、集計などの計算値を含めることができます。MongoDBでは、ビューはクエリ可能なオブジェクトであり、その内容は他のコレクションの集計パイプラインによって定義されます。

viewsプレビュー機能を使用すると、viewキーワードを使用してPrismaスキーマでビューを表すことができます。Prisma ORMでビューを使用するには、次の手順に従ってください。

viewsプレビュー機能を有効にする

ビューのサポートは現在、初期プレビュー段階です。viewsプレビュー機能を有効にするには、PrismaスキーマのgeneratorブロックのpreviewFeaturesフィールドにviewsフィーチャーフラグを追加します。

schema.prisma
generator client {
provider = "prisma-client-js"
previewFeatures = ["views"]
}

このプレビュー機能に関するフィードバックは、専用のviewsのプレビュー機能フィードバックissueに残してください。

基盤となるデータベースにビューを作成する

現在、Prisma Migrateとdb pushを使用してPrismaスキーマで定義したビューをデータベースに適用することはできません。代わりに、まず基盤となるデータベースにビューを手動で作成するか、移行の一部として作成する必要があります。

例として、Userモデルと関連するProfileモデルを含む次のPrismaスキーマを見てみましょう。

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
profile Profile?
}

model Profile {
id Int @id @default(autoincrement())
bio String
user User @relation(fields: [userId], references: [id])
userId Int @unique
}

次に、Userモデルのemailフィールドとnameフィールド、およびProfileモデルのbioフィールドを組み合わせた基盤となるデータベースのUserInfoビューを見てみましょう。

リレーショナルデータベースの場合、このビューを作成するSQLステートメントは次のとおりです。

CREATE VIEW "UserInfo" AS
SELECT u.id, email, name, bio
FROM "User" u
LEFT JOIN "Profile" p ON u.id = p."userId";

MongoDBの場合、次のコマンドを使用してビューを作成することができます。

db.createView('UserInfo', 'User', [
{
$lookup: {
from: 'Profile',
localField: '_id',
foreignField: 'userId',
as: 'ProfileData',
},
},
{
$project: {
_id: 1,
email: 1,
name: 1,
bio: '$ProfileData.bio',
},
},
{ $unwind: '$bio' },
])

Prisma Migrateとdb pushでビューを使用する

Prisma Migrateまたはdb pushを使用してPrismaスキーマに変更を適用する場合、Prisma ORMはビューに関連するSQLを作成または実行しません。

移行にビューを含めるには、migrate dev --create-onlyを実行し、ビューのSQLを移行ファイルに手動で追加します。または、データベースでビューを手動で作成することもできます。

Prismaスキーマにビューを追加する

Prismaスキーマにビューを追加するには、viewキーワードを使用します。

上記の例のUserInfoビューは、Prismaスキーマで次のように表すことができます。

view UserInfo {
id Int @unique
email String
name String
bio String
}

手書き

viewブロックは、主に次の2つの部分で構成されています。

  • viewブロック定義
  • ビューのフィールド定義

これら2つの部分を使用すると、生成されたPrisma Clientのビューの名前と、ビューのクエリ結果に存在する列を定義できます。

viewブロックを定義する

上記の例のUserInfoビューを定義するには、まずviewキーワードを使用して、UserInfoという名前のviewブロックをスキーマで定義します。

view UserInfo {
// Fields
}

フィールドを定義する

ビューのプロパティはフィールドと呼ばれ、次の要素で構成されます。

  • フィールド名
  • フィールドタイプ

UserInfoの例のビューのフィールドは、次のように定義できます。

view UserInfo {
id Int @unique
email String
name String
bio String
}

viewブロックの各フィールドは、基盤となるデータベースのビューのクエリ結果の列を表します。

イントロスペクションを使用する

警告

現在、PostgreSQL、MySQL、SQL Server、CockroachDBでのみ利用可能です。

データベースに既存のビューがある場合、イントロスペクションは、それらのビューを表すviewブロックをPrismaスキーマに自動的に生成します。

例のUserInfoビューが基盤となるデータベースに存在すると仮定すると、次のコマンドを実行すると、そのビューを表すviewブロックがPrismaスキーマに生成されます。

npx prisma db pull

結果のviewブロックは、次のように定義されます。

/// The underlying view does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
view UserInfo {
id Int?
email String?
name String?
bio String?

@@ignore
}

viewブロックは、一意の識別子が定義されていないため(現在はビューのプレビュー機能の制限事項です)、最初は@@ignore属性で生成されます。

警告

当面の間、db pullはPostgreSQL、MySQL、SQL Server、またはCockroachDBを使用している場合にのみスキーマ内のビューをイントロスペクトすることに注意してください。このワークフローのサポートは、他のデータベースプロバイダーにも拡張される予定です。

イントロスペクトされたビューに一意の識別子を追加する

イントロスペクトされたビューをPrisma Clientで使用できるようにするには、フィールドの1つまたは複数を選択して一意の識別子として定義する必要があります。

上記のビューの場合、id列は基盤となるUserテーブルの一意に識別可能なフィールドを参照しているため、そのフィールドをviewブロック内の一意に識別可能なフィールドとしても使用できます。

このviewブロックを有効にするには、次の操作を行う必要があります。

  • idフィールドからオプションフラグ?を削除する
  • @unique属性をidフィールドに追加する
  • @@ignore属性を削除する
  • 無効なビューに関する生成されたコメント警告を削除する
/// The underlying view does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
view UserInfo {
id Int?
id Int @unique
email String?
name String?
bio String?

@@ignore
}

データベースを再イントロスペクトすると、ビュー定義へのカスタム変更はすべて保持されます。

viewsディレクトリ

1つ以上の既存のビューを持つデータベースのイントロスペクションでは、prismaディレクトリ内に新しいviewsディレクトリも作成されます(Prismaバージョン4.12.0以降)。このディレクトリには、データベースのスキーマの名前が付けられたサブディレクトリが含まれており、そのスキーマでイントロスペクトされた各ビューの.sqlファイルが含まれています。各ファイルは個々のビューにちなんで名付けられ、関連するビューが定義するクエリが含まれます。

たとえば、上記のモデルを使用してデフォルトのpublicスキーマを持つデータベースをイントロスペクトした後、次の内容でprisma/views/public/UserInfo.sqlファイルが作成されていることがわかります。

SELECT
u.id,
u.email,
u.name,
p.bio
FROM
(
"User" u
LEFT JOIN "Profile" p ON ((u.id = p."userId"))
);

制限事項

一意の識別子

現在、Prisma ORMはビューをモデルと同じように扱います。これは、ビューには少なくとも1つ一意の識別子が必要であることを意味します。これは、次のいずれかで表すことができます。

  • @uniqueで示される一意制約
  • @@uniqueで示される複合一意制約
  • @idフィールド
  • @@idで示される複合識別子

リレーショナルデータベースでは、ビューの一意の識別子は、1つのフィールドの@unique属性として、または複数のフィールドの@@unique属性として定義できます。可能な場合は、@idまたは@@idフィールドよりも@uniqueまたは@@unique制約を使用することをお勧めします。

ただし、MongoDBでは、一意の識別子は、基盤となるデータベースの_idフィールドに@map("_id")でマッピングする@id属性である必要があります。

上記の例では、idフィールドに@unique属性があります。基盤となるUserテーブルの別の列が一意に識別可能として定義され、ビューのクエリ結果で利用可能になった場合、その列を一意の識別子として代わりに使用できた可能性があります。

イントロスペクション

現在、ビューのイントロスペクションは、PostgreSQL、MySQL、SQL Server、およびCockroachDBでのみ利用可能です。別のデータベースプロバイダーを使用している場合は、ビューを手動で追加する必要があります。

これは一時的な制限であり、イントロスペクションのサポートは、サポートされている他のデータソースプロバイダーにも拡張される予定です。

Prisma Clientでビューをクエリする

モデルをクエリするのと同じ方法で、Prisma Clientでビューをクエリできます。たとえば、次のクエリは、上記で定義したUserInfoビューでname'Alice'のすべてのユーザーを検索します。

const userinfo = await prisma.userInfo.findMany({
where: {
name: 'Alice',
},
})

現在、Prisma Clientでは、基盤となるデータベースが許可している場合、追加の検証なしでビューを更新できます。

特殊なタイプのビュー

このセクションでは、データベースで更新可能なビューとマテリアライズドビューをPrisma ORMで使用する方法について説明します。

更新可能なビュー

一部のデータベースは更新可能なビューをサポートしています(例:PostgreSQLMySQL、およびSQL Server)。更新可能なビューを使用すると、エントリの作成、更新、または削除が可能です。

現在、Prisma ORMはすべてのviewを更新可能なビューとして扱います。基盤となるデータベースがビューに対してこの機能をサポートしている場合、操作は成功するはずです。ビューが更新可能としてマークされていない場合、データベースはエラーを返し、Prisma Clientはこのエラーをスローします。

将来、Prisma Clientは個々のビューを更新可能または更新不可としてマークすることをサポートする可能性があります。ユースケースについて、viewsフィードバックissueにコメントしてください。

マテリアライズドビュー

一部のデータベースはマテリアライズドビューをサポートしています。例:PostgreSQLCockroachDBMongoDB、およびSQL Server(「インデックス付きビュー」と呼ばれます)。

マテリアライズドビューは、高速アクセスを実現するためにビュークエリの結果を永続化し、オンデマンドでのみ更新します。

現在、Prisma ORMはマテリアライズドビューをサポートしていません。ただし、ビューを手動で作成する場合、基盤となるデータベースの対応するコマンドを使用してマテリアライズドビューを作成することもできます。その後、Prisma ClientのTypedSQL機能を使用してコマンドを実行し、ビューを手動で更新できます。

将来、Prisma Clientは個々のビューをマテリアライズドとしてマークし、マテリアライズドビューを更新するためのPrisma Clientメソッドを追加する可能性があります。ユースケースについて、viewsフィードバックissueにコメントしてください。