如何从 Mongoose 迁移到 Prisma ORM
介绍
¥Introduction
本指南将向你展示如何将应用从 Mongoose 迁移到 Prisma ORM。我们将使用 Mongoose Express 示例 的扩展版本作为 示例项目 来演示迁移步骤。
¥This guide shows you how to migrate your application from Mongoose to Prisma ORM. We'll use an extended version of the Mongoose Express example as a sample project to demonstrate the migration steps.
你可以在 Prisma ORM 与 Mongoose 页面上了解 Prisma ORM 与 Mongoose 的比较。
¥You can learn how Prisma ORM compares to Mongoose on the Prisma ORM vs Mongoose page.
先决条件
¥Prerequisites
在开始本指南之前,请确保你已准备好:
¥Before starting this guide, make sure you have:
-
你想要迁移的 Mongoose 项目
¥A Mongoose project you want to migrate
-
已安装 Node.js(版本 18 或更高版本)
¥Node.js installed (version 18 or higher)
-
MongoDB 数据库
¥MongoDB database
-
基本了解 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:
-
安装 Prisma CLI
¥Install the Prisma CLI
-
检查你的数据库
¥Introspect your database
-
安装并生成 Prisma 客户端
¥Install and generate Prisma Client
-
逐步用 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. 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 aschema.prisma
file; your Prisma schema specifies your database connection and models -
.env
:一个位于项目根目录的dotenv
文件(如果该文件尚不存在),用于将数据库连接 URL 配置为环境变量¥
.env
: Adotenv
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 模式目前如下所示:
¥The Prisma schema currently looks as follows:
// 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 时获得最佳开发体验,请参阅 编辑器设置 了解语法高亮、格式化、自动补齐以及更多精彩功能。
¥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://USER:PASSWORD@HOST:PORT/DATABASE"
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.
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 theposts
model toauthorId
and add the@map("author")
attribute -
在
posts
模型中添加author
关系字段,并在其@relation
属性中指定fields
和references
¥Add the
author
relation field in theposts
model and it's@relation
attribute specifying thefields
andreferences
-
在
users
模型中添加posts
关系¥Add the
posts
relation in theusers
model
你的模式现在应该如下所示:
¥Your schema should now look like this:
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 tocategoryIds
and map it using@map("categories")
in theposts
model -
在
posts
模型中添加新的categories
关系字段¥Add a new
categories
relation field in theposts
model -
在
categories
模型中添加postIds
标量列表字段¥Add the
postIds
scalar list field in thecategories
model -
在
categories
模型中添加posts
关系¥Add the
posts
relation in thecategories
model -
在两个模型上都添加 关系标量
¥Add a relation scalar on both models
-
添加
@relation
属性,并在两端指定fields
和references
参数。¥Add the
@relation
attribute specifying thefields
andreferences
arguments on both sides
你的模式现在应该如下所示:
¥Your schema should now look like this:
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. Install Prisma Client
安装 Prisma 客户端包:
¥Install the Prisma Client package:
npm install @prisma/client
安装 Prisma 客户端软件包后,生成 Prisma 客户端:
¥After installing the Prisma Client package, generate Prisma Client:
npx prisma generate
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:
- 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.更新你的控制器
¥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:
- Follow us on X for announcements, live events and useful tips.
- Join our Discord to ask questions, talk to the community, and get active support through conversations.
- Subscribe on YouTube for tutorials, demos, and streams.
- Engage on GitHub by starring the repository, reporting issues, or contributing to an issue.