Prisma ORMを複数のデータベーススキーマで使用する方法
複数のデータベーススキーマのサポートは現在、PostgreSQL、CockroachDB、およびSQL Serverコネクタで利用可能です。
多くのデータベースプロバイダーでは、データベーステーブルを名前付きグループに整理できます。これを使用して、データモデルの論理構造を理解しやすくしたり、テーブル間の名前の衝突を回避したりできます。
PostgreSQL、CockroachDB、およびSQL Serverでは、これらのグループはスキーマとして知られています。Prisma ORM独自のスキーマと区別するために、これらをデータベーススキーマと呼びます。
このガイドでは、次の方法について説明します。
- Prismaスキーマに複数のデータベーススキーマを含める方法
- Prisma Migrateと
db push
を使用してデータベースにスキーマ変更を適用する方法 - 複数のデータベーススキーマを持つ既存のデータベースをイントロスペクションする方法
- Prisma Clientで複数のデータベーススキーマにまたがってクエリを実行する方法
multiSchema
プレビュー機能を有効にする方法
マルチスキーマのサポートは現在プレビュー段階です。multiSchema
プレビュー機能を有効にするには、Prismaスキーマのgenerator
ブロックのpreviewFeatures
フィールドにmultiSchema
機能フラグを追加します。
generator client {
provider = "prisma-client-js"
previewFeatures = ["multiSchema"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
Prismaスキーマに複数のデータベーススキーマを含める方法
Prismaスキーマファイルで複数のデータベーススキーマを使用するには、datasource
ブロックのschemas
フィールドにデータベーススキーマの名前を配列で追加します。次の例では、"base"
スキーマと"transactional"
スキーマを追加しています。
generator client {
provider = "prisma-client-js"
previewFeatures = ["multiSchema"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
schemas = ["base", "transactional"]
}
接続文字列を変更する必要はありません。接続文字列のschema
値は、Prisma Clientが接続してロークエリに使用するデフォルトのデータベーススキーマです。他のすべてのPrisma Clientクエリは、クエリを実行しているモデルまたはenumのスキーマを使用します。
モデルまたはenumが特定のデータベーススキーマに属するように指定するには、データベーススキーマの名前をパラメータとして持つ@@schema
属性を追加します。次の例では、User
モデルは"base"
スキーマの一部であり、Order
モデルとSize
enumは"transactional"
スキーマの一部です。
model User {
id Int @id
orders Order[]
@@schema("base")
}
model Order {
id Int @id
user User @relation(fields: [id], references: [id])
user_id Int
@@schema("transactional")
}
enum Size {
Small
Medium
Large
@@schema("transactional")
}
異なるデータベーススキーマで同じ名前のテーブルを使用する場合
異なるデータベーススキーマで同じ名前のテーブルがある場合は、Prismaスキーマでテーブル名を一意のモデル名にマッピングする必要があります。これにより、Prisma Clientでモデルをクエリするときに名前の衝突を回避できます。
たとえば、base
データベーススキーマのconfig
テーブルがusers
データベーススキーマのconfig
テーブルと同じ名前である状況を考えてみましょう。名前の衝突を避けるために、Prismaスキーマのモデルに一意の名前(BaseConfig
とUserConfig
)を付け、@@map
属性を使用して各モデルを対応するテーブル名にマッピングします。
model BaseConfig {
id Int @id
@@map("config")
@@schema("base")
}
model UserConfig {
id Int @id
@@map("config")
@@schema("users")
}
Prisma Migrateとdb push
を使用してスキーマ変更を適用する方法
Prisma Migrateまたはdb push
を使用して、複数のデータベーススキーマを持つPrismaスキーマに変更を適用できます。
例として、上記のブログ投稿モデルのbase
スキーマにProfile
モデルを追加します。
model User {
id Int @id
orders Order[]
profile Profile?
@@schema("base")
}
model Profile {
id Int @id @default(autoincrement())
bio String
user User @relation(fields: [userId], references: [id])
userId Int @unique
@@schema("base")
}
model Order {
id Int @id
user User @relation(fields: [id], references: [id])
user_id Int
@@schema("transactional")
}
enum Size {
Small
Medium
Large
@@schema("transactional")
}
その後、このスキーマ変更をデータベースに適用できます。たとえば、migrate dev
を使用して、スキーマ変更をマイグレーションとして作成および適用できます。
npx prisma migrate dev --name add_profile
モデルまたはenumをあるスキーマから別のスキーマに移動すると、Prisma ORMはソーススキーマからモデルまたはenumを削除し、ターゲットスキーマに新しいモデルまたはenumを作成することに注意してください。
複数のデータベーススキーマを持つ既存のデータベースをイントロスペクションする方法
db pull
を使用して、単一のデータベーススキーマを持つデータベースをイントロスペクションするのと同じ方法で、複数のデータベーススキーマを持つ既存のデータベースをイントロスペクションできます。
npx prisma db pull
これにより、Prismaスキーマがデータベースの現在の状態と一致するように更新されます。
異なるデータベーススキーマで同じ名前のテーブルがある場合、Prisma ORMは競合を指摘するバリデーションエラーを表示します。これを修正するには、@map
属性を使用してイントロスペクションされたモデルの名前を変更します。
Prisma Clientで複数のデータベーススキーマにまたがってクエリを実行する方法
Prisma Clientクエリ構文を変更せずに、複数のデータベーススキーマのモデルをクエリできます。たとえば、次のクエリは、上記のPrismaスキーマを使用して、特定のユーザーのすべての注文を検索します。
const orders = await prisma.order.findMany({
where: {
user: {
id: 1,
},
},
})
multiSchema
プレビュー機能の詳細
multiSchema
プレビュー機能の今後の計画、またはフィードバックについては、Github issueを参照してください。