複数のデータベーススキーマで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を削除し、ターゲットスキーマに新しいものを作成することに注意してください。
複数のデータベーススキーマを持つ既存のデータベースをイントロスペクトする方法
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を参照してください。