Skip to main content

如何从 Mongoose 迁移到 Prisma ORM

15 min

介绍

¥Introduction

本指南将向你展示如何将应用从 Mongoose 迁移到 Prisma ORM。我们将使用 示例项目 来演示迁移步骤。

¥This guide shows you how to migrate your application from Mongoose to Prisma ORM. We'll use a sample project to demonstrate the migration steps.

Prisma ORM v7 对 MongoDB 的支持

Prisma ORM v7 即将支持 MongoDB。同时,在使用 MongoDB 时,请使用 Prisma ORM v6.19(最新的 v6 版本)。

¥MongoDB support for Prisma ORM v7 is coming in the near future. In the meantime, please use Prisma ORM v6.19 (the latest v6 release) when working with MongoDB.

本指南使用 Prisma ORM v6.19 以确保与 MongoDB 完全兼容。

¥This guide uses Prisma ORM v6.19 to ensure full compatibility with MongoDB.

你可以在 Prisma ORM 与 Mongoose 页面上了解 Prisma ORM 与 Mongoose 的比较。

¥You can learn how Prisma ORM compares to Mongoose on the Prisma ORM vs Mongoose page.

警告

本指南目前假设你使用的是 Prisma ORM v6。Prisma ORM v7 与 MongoDB 的支持正在开发中。

¥This guide currently assumes you are using Prisma ORM v6. Support for Prisma ORM v7 with MongoDB is in progress.

先决条件

¥Prerequisites

在开始本指南之前,请确保你已准备好:

¥Before starting this guide, make sure you have:

  • 你想要迁移的 Mongoose 项目

    ¥A Mongoose project you want to migrate

  • Node.js 已安装 使用支持的版本

    ¥Node.js installed with the supported version

  • MongoDB 数据库(建议使用 4.2+ 版本并部署副本集)

    ¥MongoDB database (4.2+ with replica set deployment recommended)

  • 基本了解 Mongoose 和 Express.js

    ¥Basic familiarity with Mongoose and Express.js

1. 准备迁移

¥ Prepare for migration

1.1.了解迁移过程

¥1.1. Understand the migration process

无论你构建的是哪种应用或 API 层,从 Mongoose 迁移到 Prisma ORM 的步骤始终相同:

¥The steps for migrating from Mongoose to Prisma ORM are always the same, no matter what kind of application or API layer you're building:

  1. 安装 Prisma CLI

    ¥Install the Prisma CLI

  2. 检查你的数据库

    ¥Introspect your database

  3. 安装并生成 Prisma 客户端

    ¥Install and generate Prisma Client

  4. 逐步用 Prisma 客户端替换 Mongoose 查询

    ¥Gradually replace your Mongoose queries with Prisma Client

无论你是在构建 REST API(例如,使用 Express、Koa 或 NestJS)、GraphQL API(例如,使用 Apollo Server、TypeGraphQL 或 Nexus),还是任何其他使用 Mongoose 进行数据库访问的应用,这些步骤都适用。

¥These steps apply whether you're building a REST API (e.g., with Express, Koa, or NestJS), a GraphQL API (e.g., with Apollo Server, TypeGraphQL, or Nexus), or any other kind of application that uses Mongoose for database access.

1.2.安装 Prisma 依赖

¥1.2. Install Prisma dependencies

首先,安装所需的 Prisma 包:

¥First, install the required Prisma packages:

npm install prisma@6.19 @types/node --save-dev
npm install @prisma/client@6.19 dotenv
为什么选择 Prisma v6.19?

这是 Prisma ORM v6 的最新稳定版本,完全支持 MongoDB。Prisma ORM v7 即将支持 MongoDB。

¥This is the latest stable version of Prisma ORM v6 that fully supports MongoDB. MongoDB support for Prisma ORM v7 is coming soon.

你还可以安装 prisma@6@prisma/client@6 以自动获取最新的 v6 版本。

¥You can also install prisma@6 and @prisma/client@6 to automatically get the latest v6 release.

1.3.设置 Prisma 配置

¥1.3. Set up Prisma configuration

创建一个新的 Prisma 模式文件:

¥Create a new Prisma schema file:

npx prisma init --datasource-provider mongodb --output ../generated/prisma

此命令将创建:

¥This command creates:

  • 一个名为 prisma 的新目录,其中包含一个 schema.prisma 文件;你的 Prisma 模式指定了你的数据库连接和模型

    ¥A new directory called prisma that contains a schema.prisma file; your Prisma schema specifies your database connection and models

  • .env:一个位于项目根目录的 dotenv 文件(如果该文件尚不存在),用于将数据库连接 URL 配置为环境变量

    ¥.env: A dotenv file at the root of your project (if it doesn't already exist), used to configure your database connection URL as an environment variable

  • prisma.config.ts:Prisma 配置文件

    ¥prisma.config.ts: Configuration file for Prisma

Prisma schema 使用 ESM 优先的 prisma-client 生成器:

¥The Prisma schema uses the ESM-first prisma-client generator:

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

datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}

提示

为了在使用 Prisma ORM 时获得最佳开发体验,请参阅 编辑器设置 了解语法高亮、格式化、自动补齐以及更多精彩功能。

¥For an optimal development experience when working with Prisma ORM, refer to editor setup to learn about syntax highlighting, formatting, auto-completion, and many more cool features.

使用 MongoDB 连接字符串更新 .env 文件中的 DATABASE_URL

¥Update the DATABASE_URL in the .env file with your MongoDB connection string:

DATABASE_URL="mongodb+srv://username:password@cluster.mongodb.net/mydb"
提示

usernamepasswordclustermydb 替换为你的实际 MongoDB 凭据和数据库名称。你可以从 MongoDB 阿特拉斯 或你的 MongoDB 部署中获取连接字符串。

¥Replace username, password, cluster, and mydb with your actual MongoDB credentials and database name. You can get your connection string from MongoDB Atlas or your MongoDB deployment.

1.4.配置 Prisma

¥1.4. Configure Prisma

生成的 prisma.config.ts 文件应如下所示:

¥The generated prisma.config.ts file should look like this:

prisma.config.ts
import { defineConfig, env } from 'prisma/config'

export default defineConfig({
schema: 'prisma/schema.prisma',
migrations: {
path: 'prisma/migrations',
},
engine: "classic",
datasource: {
url: env('DATABASE_URL'),
},
})

添加 dotenv 以从 .env 文件加载环境变量:

¥Add dotenv to load environment variables from your .env file:

prisma.config.ts
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config'

export default defineConfig({
schema: 'prisma/schema.prisma',
migrations: {
path: 'prisma/migrations',
},
engine: "classic",
datasource: {
url: env('DATABASE_URL'),
},
})

2. 迁移数据库模式

¥ Migrate the database schema

2.1.检查你的数据库

¥2.1. Introspect your database

警告

MongoDB 是一个无模式数据库。要在你的项目中逐步采用 Prisma ORM,请确保你的数据库中已填充示例数据。Prisma ORM 通过对存储的数据进行采样并从数据库中的数据推断出模式来自检 MongoDB 模式。

¥MongoDB is a schemaless database. To incrementally adopt Prisma ORM in your project, ensure your database is populated with sample data. Prisma ORM introspects a MongoDB schema by sampling data stored and inferring the schema from the data in the database.

运行 Prisma 的自省功能,从现有数据库创建 Prisma 模式:

¥Run Prisma's introspection to create the Prisma schema from your existing database:

npx prisma db pull

这将创建一个包含数据库架构的 schema.prisma 文件。

¥This will create a schema.prisma file with your database schema.

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.更新关系

¥2.2. Update relations

MongoDB 不支持不同集合之间的关系。但是,你可以使用 ObjectId 字段类型在文档之间创建引用,或者使用集合中的 ObjectIds 数组在文档之间创建引用。该引用将存储相关文档的 ID。你可以使用 Mongoose 提供的 populate() 方法,将相关文档的数据填充到引用中。

¥MongoDB doesn't support relations between different collections. However, you can create references between documents using the ObjectId field type or from one document to many using an array of ObjectIds in the collection. The reference will store id(s) of the related document(s). You can use the populate() method that Mongoose provides to populate the reference with the data of the related document.

更新 posts <-> users 之间的 1-n 关系,如下所示:

¥Update the 1-n relationship between posts <-> users as follows:

  • posts 模型中现有的 author 引用重命名为 authorId,并添加 @map("author") 属性

    ¥Rename the existing author reference in the posts model to authorId and add the @map("author") attribute

  • posts 模型中添加 author 关系字段,并在其 @relation 属性中指定 fieldsreferences

    ¥Add the author relation field in the posts model and it's @relation attribute specifying the fields and references

  • users 模型中添加 posts 关系

    ¥Add the posts relation in the users model

你的模式现在应该如下所示:

¥Your schema should now look like this:

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 引用之间的 m-n,如下所示:

¥Then, update the m-n between posts <-> categories references as follows:

  • categories 字段重命名为 categoryIds,并在 posts 模型中使用 @map("categories") 进行映射

    ¥Rename the categories field to categoryIds and map it using @map("categories") in the posts model

  • posts 模型中添加新的 categories 关系字段

    ¥Add a new categories relation field in the posts model

  • categories 模型中添加 postIds 标量列表字段

    ¥Add the postIds scalar list field in the categories model

  • categories 模型中添加 posts 关系

    ¥Add the posts relation in the categories model

  • 在两个模型上都添加 关系标量

    ¥Add a relation scalar on both models

  • 添加 @relation 属性,并在两端指定 fieldsreferences 参数。

    ¥Add the @relation attribute specifying the fields and references arguments on both sides

你的模式现在应该如下所示:

¥Your schema should now look like this:

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. 更新你的应用代码

¥ Update your application code

3.1.生成 Prisma 客户端

¥3.1. Generate Prisma Client

根据你的 schema 生成 Prisma Client:

¥Generate Prisma Client based on your schema:

npx prisma generate

这将在 generated/prisma 目录中创建一个类型安全的 Prisma 客户端。

¥This creates a type-safe Prisma Client in the generated/prisma directory.

3.2.替换 Mongoose 查询

¥3.2. Replace Mongoose queries

开始使用 Prisma 客户端替换你的 Mongoose 查询。以下是如何转换一些常见查询的示例:

¥Start replacing your Mongoose queries with Prisma Client. Here's an example of how to convert some common queries:

// 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.更新你的控制器

¥3.3. Update your controllers

更新 Express 控制器以使用 Prisma 客户端。例如,以下是如何更新用户控制器:

¥Update your Express controllers to use Prisma Client. For example, here's how to update a user controller:

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)
}
}

下一步

¥Next steps

现在你已经迁移到 Prisma ORM,你可以:

¥Now that you've migrated to Prisma ORM, you can:

  • 使用 Prisma 强大的查询 API 添加更复杂的查询

    ¥Add more complex queries using Prisma's powerful query API

  • 设置 Prisma Studio 进行数据库管理

    ¥Set up Prisma Studio for database management

  • 实现数据库监控

    ¥Implement database monitoring

  • 使用 Prisma 的测试实用程序

    ¥Add automated tests using Prisma's testing utilities

更多信息:

¥For more information:


Stay connected with Prisma

Continue your Prisma journey by connecting with our active community. Stay informed, get involved, and collaborate with other developers:

We genuinely value your involvement and look forward to having you as part of our community!