MongooseからPrisma ORMへの移行方法
はじめに
このガイドでは、MongooseからPrisma ORMへアプリケーションを移行する方法を説明します。移行手順を示すためのMongoose Expressの拡張例をサンプルプロジェクトとして使用します。
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()
メソッドを使用して、参照を関連ドキュメントのデータで埋めることができます。
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. コントローラーを更新する
ExpressコントローラーをPrisma Clientを使用するように更新します。たとえば、ユーザーコントローラーを更新する方法は次のとおりです。
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で関わる リポジトリにスターを付けたり、問題を報告したり、問題に貢献したりしてください。