跳到主要内容

如何从 Mongoose 迁移到 Prisma ORM

简介

本指南向您展示如何将您的应用程序从 Mongoose 迁移到 Prisma ORM。我们将使用 Mongoose Express 示例 的扩展版本作为示例项目来演示迁移步骤。

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

前提条件

在开始本指南之前,请确保您已具备:

  • 一个您想要迁移的 Mongoose 项目
  • 安装了 Node.js(版本 18 或更高版本)
  • MongoDB 数据库
  • 熟悉 Mongoose 和 Express.js 的基本知识

1. 准备迁移

1.1. 了解迁移过程

无论您正在构建什么类型的应用程序或 API 层,从 Mongoose 迁移到 Prisma ORM 的步骤始终相同

  1. 安装 Prisma CLI
  2. 内省您的数据库
  3. 安装并生成 Prisma 客户端
  4. 逐步用 Prisma 客户端替换您的 Mongoose 查询

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

1.2. 设置 Prisma 配置

创建一个新的 Prisma 模式文件

npx prisma init --datasource-provider mongodb

此命令将创建

  • 一个名为 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 时获得最佳的开发体验,请参阅 编辑器设置,了解有关语法高亮、格式化、自动完成以及更多炫酷功能的信息。

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

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 字段类型在文档之间创建引用,或者使用集合中 ObjectIds 的数组从一个文档引用到多个文档。引用将存储相关文档的 ID。您可以使用 Mongoose 提供的 populate() 方法使用相关文档的数据填充引用。

按如下方式更新 posts <-> users 之间的 1-n 关系

  • posts 模型中现有的 author 引用重命名为 authorId 并添加 @map("author") 属性
  • posts 模型中添加 author 关系字段,并使用 @relation 属性指定 fieldsreferences
  • 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 之间 m-n 的引用

  • categories 字段重命名为 categoryIds 并使用 posts 模型中的 @map("categories") 进行映射
  • posts 模型中添加新的 categories 关系字段
  • categories 模型中添加 postIds 标量列表字段
  • categories 模型中添加 posts 关系
  • 在两个模型上添加一个 关系标量
  • 在两侧添加 @relation 属性,指定 fieldsreferences 参数

您的模式现在应该如下所示

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 客户端

安装 Prisma 客户端包

npm install @prisma/client

安装 Prisma 客户端包后,生成 Prisma 客户端

npx prisma generate

3.2. 替换 Mongoose 查询

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

// Find one
const user = await User.findById(id);

// Create
const user = await User.create({
email: '[email protected]',
name: 'Alice'
});

// Update
await User.findByIdAndUpdate(id, {
name: 'New name'
});

// Delete
await User.findByIdAndDelete(id);

3.3. 更新您的控制器

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

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 的测试实用程序添加自动化测试

有关更多信息和更新