Skip to main content

如何从 Mongoose 迁移到 Prisma ORM

15 min

介绍

¥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:

  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. 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 模式目前如下所示:

¥The Prisma schema currently looks as follows:

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 时获得最佳开发体验,请参阅 编辑器设置 了解语法高亮、格式化、自动补齐以及更多精彩功能。

¥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.

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. 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:

// 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!