Mongoose から Prisma ORM への移行方法
はじめに
このガイドでは、アプリケーションを Mongoose から Prisma ORM に移行する方法について説明します。移行手順を示すサンプルプロジェクトとして、Mongoose Express の拡張版の例を使用します。Mongoose Express example を sample project として使用します。
Prisma ORM と Mongoose の比較については、「Prisma ORM vs Mongoose」のページをご覧ください。
前提条件
このガイドを開始する前に、以下をご確認ください
- 移行したい Mongoose プロジェクト
- Node.js がインストールされていること(バージョン 18 以降)
- MongoDB データベース
- Mongoose および Express.js の基本的な知識
1. 移行の準備
1.1. 移行プロセスを理解する
Mongoose から Prisma ORM への移行手順は、構築しているアプリケーションや API レイヤーの種類に関係なく常に同じです
- Prisma CLI をインストールする
- データベースをイントロスペクションする
- Prisma Client をインストールして生成する
- Mongoose クエリを Prisma Client に徐々に置き換える
これらの手順は、REST API(例:Express、Koa、NestJS を使用)、GraphQL API(例:Apollo Server、TypeGraphQL、Nexus を使用)、またはデータベースアクセスに Mongoose を使用するその他の種類のアプリケーションを構築している場合でも適用されます。
1.2. Prisma 設定をセットアップする
新しい Prisma スキーマファイルを作成する
npx prisma init --datasource-provider mongodb --output ../generated/prisma
このコマンドは以下を作成します
- `prisma` という名前の新しいディレクトリ。このディレクトリには `schema.prisma` ファイルが含まれています。Prisma スキーマは、データベース接続とモデルを指定します
- .env: プロジェクトのルートにある dotenv ファイル(まだ存在しない場合)。データベース接続 URL を環境変数として設定するために使用されます
現在、Prisma スキーマは次のようになっています
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
Prisma ORM を使用した最適な開発体験を得るには、エディターのセットアップを参照して、構文の強調表示、フォーマット、自動補完、その他多くの優れた機能について学んでください。
.env ファイルの DATABASE_URL を MongoDB 接続文字列で更新します
DATABASE_URL="mongodb://USER:PASSWORD@HOST:PORT/DATABASE"
2. データベーススキーマを移行する
2.1. データベースをイントロスペクションする
MongoDB はスキーマレスデータベースです。プロジェクトで Prisma ORM を段階的に採用するには、データベースにサンプルデータが投入されていることを確認してください。Prisma ORM は、保存されているデータをサンプリングし、データベース内のデータからスキーマを推測することで、MongoDB スキーマをイントロスペクションします。
Prisma のイントロスペクションを実行して、既存のデータベースから Prisma スキーマを作成します
npx prisma db pull
これにより、データベーススキーマを含む schema.prisma ファイルが作成されます。
type UsersProfile {
bio String
}
model categories {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
name String
}
model posts {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
author String @db.ObjectId
categories String[] @db.ObjectId
content String
published Boolean
title String
}
model users {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
email String @unique(map: "email_1")
name String
profile UsersProfile?
}
2.2. リレーションを更新する
MongoDB は、異なるコレクション間のリレーションをサポートしていません。ただし、ObjectId フィールドタイプを使用してドキュメント間の参照を作成したり、コレクション内の ObjectId の配列を使用して 1 つのドキュメントから多数のドキュメントへの参照を作成したりできます。参照には、関連ドキュメントの ID が格納されます。Mongoose が提供する populate() メソッドを使用して、関連ドキュメントのデータで参照を population できます。
posts <-> users 間の 1 対多のリレーションシップを次のように更新します
- posts モデルの既存の author 参照を authorId に名前変更し、@map("author") 属性を追加します
- posts モデルに author リレーションフィールドを追加し、fields と references を指定する @relation 属性を追加します
- users モデルに posts リレーションを追加します
スキーマは次のようになります
type UsersProfile {
bio String
}
model categories {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
name String
}
model posts {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
content String
published Boolean
v Int @map("__v")
author String @db.ObjectId
author users @relation(fields: [authorId], references: [id])
authorId String @map("author") @db.ObjectId
categories String[] @db.ObjectId
}
model users {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
email String @unique(map: "email_1")
name String
profile UsersProfile?
posts posts[]
}
次に、posts <-> categories 間の多対多の参照を次のように更新します
- posts モデルの categories フィールドを categoryIds に名前変更し、@map("categories") を使用してマッピングします
- posts モデルに新しい categories リレーションフィールドを追加します
- categories モデルに postIds スカラーリストフィールドを追加します
- categories モデルに posts リレーションを追加します
- 両方のモデルに関係スカラーを追加します
- 両側で fields および references 引数を指定する @relation 属性を追加します
スキーマは次のようになります
type UsersProfile {
bio String
}
model categories {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
name String
posts posts[] @relation(fields: [postIds], references: [id])
postIds String[] @db.ObjectId
}
model posts {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
content String
published Boolean
v Int @map("__v")
author users @relation(fields: [authorId], references: [id])
authorId String @map("author") @db.ObjectId
categories String[] @db.ObjectId
categories categories[] @relation(fields: [categoryIds], references: [id])
categoryIds String[] @map("categories") @db.ObjectId
}
model users {
id String @id @default(auto()) @map("_id") @db.ObjectId
v Int @map("__v")
email String @unique(map: "email_1")
name String
profile UsersProfile?
posts posts[]
}
3. アプリケーションコードを更新する
3.1. Prisma Client をインストールする
Prisma Client パッケージをインストールする
npm install @prisma/client
Prisma Client パッケージをインストールしたら、Prisma Client を生成します
npx prisma generate
3.2. Mongoose クエリを置き換える
Mongoose クエリを Prisma Client に置き換え始めます。一般的なクエリを変換する方法の例を次に示します
- Mongoose
- Prisma Client
// Find one
const user = await User.findById(id);
// Create
const user = await User.create({
email: 'alice@prisma.io',
name: 'Alice'
});
// Update
await User.findByIdAndUpdate(id, {
name: 'New name'
});
// Delete
await User.findByIdAndDelete(id);
// Find one
const user = await prisma.user.findUnique({
where: { id }
});
// Create
const user = await prisma.user.create({
data: {
email: 'alice@prisma.io',
name: 'Alice'
}
});
// Update
await prisma.user.update({
where: { id },
data: { name: 'New name' }
});
// Delete
await prisma.user.delete({
where: { id }
});
3.3. コントローラーを更新する
Prisma Client を使用するように Express コントローラーを更新します。たとえば、ユーザーコントローラーを更新する方法を次に示します
import { prisma } from '../client'
export class UserController {
async create(req: Request, res: Response) {
const { email, name } = req.body
const result = await prisma.user.create({
data: {
email,
name,
},
})
return res.json(result)
}
}
次のステップ
Prisma ORM に移行したので、次のことができます
- Prisma の強力なクエリ API を使用して、より複雑なクエリを追加する
- データベース管理のために Prisma Studio をセットアップする
- データベース監視を実装する
- Prisma のテストユーティリティを使用して自動テストを追加する
詳細については
Prisma とのつながりを保つ
以下とつながって Prisma の旅を続けましょう 私たちのアクティブなコミュニティ。最新情報を入手し、参加して、他の開発者と協力してください
- X でフォローしてください お知らせ、ライブイベント、役立つヒントをお届けします。
- Discord に参加してください 質問をしたり、コミュニティと話したり、会話を通じて積極的なサポートを得たりできます。
- YouTube で購読してください チュートリアル、デモ、ストリームを提供しています。
- GitHub で交流してください リポジトリにスターを付けたり、問題を報告したり、問題に貢献したりしてください。