💽

Prismaで複数のデータベースを同時に扱う

2021/07/27に公開

はじめに

prismaについてはこちら
参考資料

対象読者

  • Prismaを使っている
  • Node.jsを使っている(もしくは個別に変換して解釈できる)
  • 複数のデータベースを同じプロジェクトで扱う必要がある
  • とりあえず動かしたい

手順

  1. Prisma schemaの作成
  2. Prisma clientの生成
  3. Clientのインポート&初期化
  4. それぞれのクライアントを使う

Prisma schemaの作成

Prismaで複数のデータベースを同時に扱うには、Schemaを複数作成する必要があります。
また、generatorの設定にoutputの項目を追加することで/prisma/generateの中にそれぞれの名前でPrisma clientファイルが生成されます

serviceA.schema
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL_SERVICE_A")
}

generator client {
  provider = "prisma-client-js"
  output   = "./generated/service_a"
}

model user {
  id   String  @id
  name String
}
serviceB.schema
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL_SERVICE_B")
}

generator client {
  provider = "prisma-client-js"
  output   = "./generated/service_b"
}

model user {
  id   String  @id
  name String
}

Prisma clientの生成

普通にprisma.schema単体で使う場合はprisma generateだけでもPrisma CLIが良しなにやってくれるのですが、複数のschemaファイルがある場合にはそれぞれを指定してあげる必要があります。

実際にクライアントを生成する

shell
$ # コマンド例
$ # prisma generate --schema {Schemaのパス}/{Schemaファイル名}
$ 
$ prisma generate --schema prisma/serviceA.prisma
$ prisma generate --schema prisma/serviceB.prisma

上記コマンドを実行すると/prisma/generated/に生成されたそれぞれのデータベース用のクライアントが生成されます。

package.json
"scripts": {
  ....
  "prisma:migrate:all": "npx pnpm migrate --schema prisma/own-auth.prisma --preview-feature && npx pnpm migrate --schema prisma/own-developer.prisma --preview-feature",
  "prisma:generate:all": "prisma generate --schema prisma/own-auth.prisma && prisma generate --schema prisma/own-developer.prisma"
}

Clientのインポート&初期化

それぞれのクライアントを初期化する際にデータベースを指定してあげる必要があります。

prisma.ts
// それぞれのクライアントをインポート
import { PrismaClient as serviecA } from '@prisma/generated/own-auth-client'
import { PrismaClient as serviecB } from '@prisma/generated/own-developer-client'
import { PrismaClient } from '@prisma/client'

// クライアント生成時の例
// export const clientX = new serviecB({
//   datasources: { db: { url: '{db_provider}://{db_url}/{table_name}' } },
// })

// ServiceAのクライアント生成
export const clientA = new serviecA({
  datasources: { db: { url: 'postgres://localhost:5432/service_a' } },
})

// ServiceBのクライアント生成
export const clientB = new serviecB({
  datasources: { db: { url: 'postgres://localhost:5432/service_b' } },
})

それぞれのクライアントを使う

serviceA, serviceBのデータベースに対してそれぞれのuserテーブルのデータをIDをキーにして検索&取得するコードの例です。

index.ts
import { clientA, clientB } from './prisma.ts'

export const findNameFromClientA = async (userId: string) => {
  return await clientA.user.findUnique({
    where: { id: userId },
  })
}

export const findNameFromClientB = async (userId: string) => {
  return await clientB.user.findUnique({
    where: { id: userId },
  })
}

Discussion