Type safety with Prisma & MongoDB
你是否已经知道 Prisma 现在已经支持了 MongoDB?在本文中,我们来看看如何使用 Prisma 连接 MongoDB。
Prisma 是什么?
Prisma 是一个开源的 ORM(Object Relational Mapper),它用于 Node.js。同时也支持 JavaScript 和 TypeScrpt。当使用 TypeScrpt 时它会显得更加出色,它能够帮你编写出可读且类型安全的代码。
为什么使用 Prisma?
Schemas 可以帮助开发者避免随着时间的推移出现的数据不一致问题。虽然你可以在 MongoDB 中的数据库级别定义 schema,但是 Prisma 允许你在应用程序级别定义 schema。当使用 Prisma Client 时,开发者可以借助自动补全查询,这得益于 Prisma Client 对 schema 的感知。
数据建模
通常来说,在 MongoDB 数据库中,需要一次查询访问的数据应该存储在一起。Prisma 支持使用嵌入式文档来确保数据存在一起。
但是,也有一些使用场景,你需要将相关联的数据存储到不同的 collection 中。要在 MongoDB 中做到这些,你可以将一个文档的_id 存到另外一个文档中。在这种情况下,Prisma 可以帮你组织这些相关联的数据,并维护这些数据的引用完整性。
Prisma & MongoDB 实践
我们将从 Prisma 的 prisma-examples
仓库中获取一个现有的示例项目。
其中有一个示例是博客内容管理平台。这个示例用了 SQLite 数据库。我们把它转换成 MongoDB 并且插入一些虚拟种子数据。
如果你想查看最终的代码,可以在这个专门的仓库中找到它。
MongoDB Atlas 配置
在本文中,我们将使用一个 MongoDB Atlas 集群。想要创建一个免费账号和一个永久免费的集群,可以点击这里 - Get Started with Atlas guide。
Prisma 配置
首先我们需要先设置环境变量来连接我们的 MongoDB Atlas 数据库。在 .env
文件中间添加 MongoDB Atlas 连接字符串。
示例:
DATABASE_URL="mongodb+srv://<username>:<password>@<cluster>.mongodb.net/prisma?retryWrites=true&w=majority"
你可以在 Atlas 的仪表盘中得到你的连接字符串。
现在,让我们编辑 schema.prisma
文件。
如果你使用 Visual Studio Code,确保你安装了官方的 Prisma VS Code 插件,来帮我们格式化和自动补全。
同样的,也可以安装官方的 MogonDB VS Code 插件,在 VS Code 中直接监控你的数据库。
在 datasource db
对象中,我们将 provider
设置为 “mongodb”
,url
设置为我们的环境变量 DATABASE_URL
。
对于 User
模型,我们需要更新 id
。我们将使用 String
替换原来的 Int
。再将它的默认值设置为 auto()
。因为 MongoDB 的 id
字段命名是 _id
,所以我们需要将 id
字段映射为 _id
。最后,告诉 Prisma 要使用 ObjectId
作为 id
字段的数据类型。
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
email String @unique
name String?
posts Post[]
}
model Post {
id String @id @default(auto()) @map("_id") @db.ObjectId
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String
content String?
published Boolean @default(false)
viewCount Int @default(0)
author User @relation(fields: [authorId], references: [id])
authorId String @db.ObjectId
}
在 MongoDB 中这个 schema 将会导致生成单独的 User
和 Post
表。每个文章将会有一个关联的用户。
目前为止已经设置好了 schema,接下来我们开始安装依赖包并生成我们的 schema。
npm install
npx prisma generate
如果你稍后对 schema 做了任何修改,你需要重新运行
npx prisma genera
。
创建 MongoDB 数据库并插入种子数据
接下来,我们需要在数据库插入一些种子数据。仓库中已经有了一个自带虚拟数据的种子文件 prisma/seed.ts
。 那么,让我们运行以下命令向数据库插入种子数据:
npx prisma db seed
这同样也会创建在 prisma/schema.prisma
中定义的 User
和 Post
表。
示例代码的其他更新
因为我们修改了 id
的数据类型,所以必须更新一些示例代码来反应这些改动。
这些更新在 pages/api/post/[id].ts
和 pages/api/publish/[id].ts
文件中。 这是其中一个例子。我们需要从对 id
字段的引用中删除 Number()
调用,因为它现在是一个 String
了。
// BEFORE
async function handleGET(postId, res) {
const post = await prisma.post.findUnique({
where: { id: Number(postId) },
include: { author: true },
})
res.json(post)
}
// AFTER
async function handleGET(postId, res) {
const post = await prisma.post.findUnique({
where: { id: postId },
include: { author: true },
})
res.json(post)
}
优秀的自动补全 & 智能感知
注意在这个文件中,当鼠标悬停到 post
变量时,VS Code 就感知到了 Post
类型。如果我们只是想要一个特定的字段,VS Code 会自动感知包含哪些字段。不用怀疑!
运行应用
以上就是所需的全部更新。我们现在可以运行这个应用,而且我们应该看到种子数据已经出现了。
npm run dev
在浏览器中打开应用 http://localhost:3000/
。
在主页面,你可以点击查看一篇文章。也可以在该页面删除文章。
我们可以到 Drafts 页面去查看所有未发布的文章。当我们点击任何一个未发布的文章,我们可以发布或者删除它。
“Signup” 按钮允许我们添加一个新用户到数据库中。
而且,最后,我们还可以通过点击 “Create draft” 按钮来创建一篇新的文章。
所有这些操作都由 Prisma 客户端使用我们应用中定义好的 API 路由来执行。
打开 pages/api
文件夹来深入了解 API 路由(译者注:项目使用的是 Next.js 框架)。
总结
Prisma 让 MongoDB 中的 schema 处理变得轻而易举。尤其是在使用 TypeScript 时它会显得更加出色,它可以让你的代码可读且类型安全。它还有助于你通过参照完整性来管理多个集合关系。
我可以看到在应用程序级别定义 schema 的好处,并且将来也会使用 Prisma 来连接 MongoDB。
加入 MongoDB 社区,让我们了解你的想法。
完。
原作者:Jesse Hall (译者注:作者系 MongoDB 开发者社区活跃的全栈开发专家)
发表于:2022年4月25日