メインコンテンツへスキップ

Mongoose から Prisma ORM への移行方法

15 分

はじめに

このガイドでは、アプリケーションを Mongoose から Prisma ORM に移行する方法について説明します。移行手順を示すサンプルプロジェクトとして、Mongoose Express の拡張版の例を使用します。Mongoose Express examplesample project として使用します。

Prisma ORM と Mongoose の比較については、「Prisma ORM vs Mongoose」のページをご覧ください。

前提条件

このガイドを開始する前に、以下をご確認ください

  • 移行したい Mongoose プロジェクト
  • Node.js がインストールされていること(バージョン 18 以降)
  • MongoDB データベース
  • Mongoose および Express.js の基本的な知識

1. 移行の準備

1.1. 移行プロセスを理解する

Mongoose から Prisma ORM への移行手順は、構築しているアプリケーションや API レイヤーの種類に関係なく常に同じです

  1. Prisma CLI をインストールする
  2. データベースをイントロスペクションする
  3. Prisma Client をインストールして生成する
  4. 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 スキーマは次のようになっています

prisma/schema.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 ファイルが作成されます。

prisma/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 リレーションを追加します

スキーマは次のようになります

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
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 属性を追加します

スキーマは次のようになります

schema.prisma
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 に置き換え始めます。一般的なクエリを変換する方法の例を次に示します

// 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);

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 の旅を続けましょう 私たちのアクティブなコミュニティ。最新情報を入手し、参加して、他の開発者と協力してください

皆様のご参加を心より歓迎し、コミュニティの一員としてお迎えできることを楽しみにしています!