从 Mongoose 到 MongoDB 的 Prisma ORM 之旅!
Prisma是用于 NodeJS 和 TypeScript 环境的下一代 ORM。它支持多种数据库,例如 MySQL、SQLite、PostgreSQL、MSSQL 和 MongoDB。 [](https://res.cloudinary.com/practicaldev/image/fetch/s--03TVNXC_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq
Prisma是用于 NodeJS 和 TypeScript 环境的下一代 ORM。它支持多种数据库,例如 MySQL、SQLite、PostgreSQL、MSSQL 和 MongoDB。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--03TVNXC_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to -uploads.s3.amazonaws.com/uploads/articles/6asm3c1uhmis3ktx9sih.png)
来源:棱镜
所以在这篇文章中,让我们谈谈全新的 Prisma MongoDB 连接器,它的操作以及是什么让我从 Mongoose 切换到 Prisma for MongoDB。
连接
让我们首先建立与我们的 MongoDB 服务器的连接。在您的 Prisma schema 文件中,我们需要更改provider
。
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
进入全屏模式 退出全屏模式
prisma.schema
文件允许我们指定我们希望 Prisma 如何连接到我们的数据库。我们需要告诉它我们想使用什么样的提供者——在这个例子中是mongodb
——和一个url
来连接——这是指向一个环境变量,因为我们想保密。我们将使用 MongoDB 连接字符串作为DATABASE_URL
,它可以在/prisma/.env
文件中找到。
接下来我们需要设置生成器块,如下所示。
generator client {
provider = "prisma-client-js"
previewFeatures = ["mongoDb"]
}
进入全屏模式 退出全屏模式
由于 Prisma MongoDB 连接器仍处于预览阶段,我们需要明确指定previewFeatures
键。
定义模型
所以现在已经成功建立到 MongoDB 服务器的连接,现在让我们为我们的数据库集合创建模型。
一个典型的 MongoDB 文档如下所示:
{
"_id": { "$oid": "60d599cb001ef98000f2cad2" },
"email": "somsubhra@email.com",
"name": "Somsubhra",
}
进入全屏模式 退出全屏模式
那么现在如何在 Prisma 中定义这样的模型呢?在 Prisma schema 文件中,我们可以定义我们的模型。
model User {
id String @id @default(dbgenerated()) @map("_id") @db.ObjectId
email String @unique
name String?
posts Post[]
}
model Post {
id String @id @default(dbgenerated()) @map("_id")
published Boolean @default(false)
title String
user User? @relation(fields: [userId], references: [id])
userId String?
}
进入全屏模式 退出全屏模式
将其与 mongoose 模型进行比较,在 Mongoose ODM 中,我们会编写如下内容:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: String,
email: {
type: String,
unique: true,
},
});
module.exports = User = mongoose.model("user", UserSchema);
进入全屏模式 退出全屏模式
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const PostSchema = new Schema({
title: String,
user: {
type: mongoose.Types.ObjectId,
ref: "user",
},
published: {
type: Boolean
default: false,
},
});
module.exports = Post = mongoose.model("post", PostSchema);
进入全屏模式 退出全屏模式
在Prisma中,我们也可以使用bson
包手动生成 ObjectId。
import { ObjectId } from "bson";
const id = new ObjectId();
进入全屏模式 退出全屏模式
查询和数据库操作
现在让我们了解如何使用 Prisma 和 Mongoose 编写查询和操作到 MongoDB。
获取单条记录
在 prisma 中获取单个记录是使用where
属性完成的,但在 mongoose 中它具有findById
方法。
棱镜
const user = await prisma.user.findUnique({
where: {
id: ObjectId('5eb9354624286a04e42401d8'),
},
})
进入全屏模式 退出全屏模式
猫鼬
const result = await User.findById('5eb9354624286a04e42401d8')
进入全屏模式 退出全屏模式
获取单个记录的选定值
在 Prisma ORM 中,通过仅使用单个查询函数进行选择操作,获取单个记录的选定值比以往任何时候都容易,而在 Mongoose 中,在找到记录后,我们需要将输出与select()
链接起来。这增加了时间复杂度,也减慢了速度过程。
棱镜
const user = await prisma.user.findUnique({
where: {
id: ObjectId('5eb9354624286a04e42401d8'),
},
select: {
name: true,
},
})
进入全屏模式 退出全屏模式
猫鼬
const user = await User.findById('5eb9354624286a04e42401d8').select(['name', 'email'])
进入全屏模式 退出全屏模式
获取关系
在 Prisma 中,我们使用include
属性,但在 Mongoose 中,我们必须使用populate()
方法。
棱镜
const posts = await prisma.user.findUnique({
where: {
id: ObjectId('5eb9354624286a04e42401d8'),
},
include: {
post: true,
},
})
进入全屏模式 退出全屏模式
猫鼬
const userWithPosts = await User.findById(id).populate('posts')
进入全屏模式 退出全屏模式
过滤值
在 Prisma 中,我们使用where
属性过滤记录,而在 Mongoose 中,我们使用find()
。
棱镜
const posts = await prisma.post.findMany({
where: {
title: {
contains: 'Hello World',
},
},
})
进入全屏模式 退出全屏模式
猫鼬
const post = await Post.find({
title: 'Hello World',
})
进入全屏模式 退出全屏模式
关系过滤
棱镜
Prisma 可以根据一个标准过滤列表,该标准不仅适用于正在检索的列表的模型,而且适用于该模型的关系。
const posts = await prisma.user.findMany({
where: {
posts: {
some: {
title: {
contains: 'Hello',
},
},
},
},
})
进入全屏模式 退出全屏模式
猫鼬
Mongoose 不为关系过滤器提供此功能。我们可以通过添加一个额外的步骤来过滤查询返回的结果来实现类似的功能,但这会导致查询时间和大型数据库的负载增加。
分页
棱镜
光标式分页:
const page = prisma.post.findMany({
before: {
id: ObjectId('6eb93546f4w5486a04e42401d8'),
},
last: 20,
})
进入全屏模式 退出全屏模式
偏移分页:
const cc = prisma.post.findMany({
skip: 200,
first: 20,
})
进入全屏模式 退出全屏模式
猫鼬
Mongoose 也有类似的分页实现。
const posts = await Post.find({
skip: 5,
limit: 10,
})
进入全屏模式 退出全屏模式
创建记录
棱镜
const user = await prisma.user.create({
data: {
email: 'user@email.com',
},
})
进入全屏模式 退出全屏模式
猫鼬
const user = await User.create({
name: 'John',
email: 'user@email.com',
})
进入全屏模式 退出全屏模式
更新记录
与我们需要使用$set
运算符的 mongoose 相比,Prisma 直接使用 data 属性中传递的值更新记录。
棱镜
const user = await prisma.user.update({
data: {
name: 'John',
},
where: {
id: ObjectId('5eb9354624286a04e42401d8'),
},
})
进入全屏模式 退出全屏模式
猫鼬
const updatedUser = await User.findOneAndUpdate(
{ _id: id },
{
$set: {
name: 'John',
},
}
)
进入全屏模式 退出全屏模式
删除单条记录
棱镜
const user = await prisma.user.delete({
where: {
id: ObjectId('5eb9354624286a04e42401d8'),
},
})
进入全屏模式 退出全屏模式
猫鼬
await User.findByIdAndDelete(id)
进入全屏模式 退出全屏模式
删除多条记录
棱镜
const users = await prisma.user.deleteMany({
where: {
id: {
in: [1, 2, 6, 34],
},
},
})
进入全屏模式 退出全屏模式
猫鼬
await User.deleteMany({ _id: { $in: [1, 2, 6, 34] } })
进入全屏模式 退出全屏模式
Prisma 相对于 Mongoose 的优势
所以现在我们知道了 Prisma 和 Mongoose 之间的操作差异,现在让我们关注 Prisma 相对于 Mongoose 提供的优势。
-
Prisma 允许 TypeSafe 数据库访问。
-
Prisma 有一个自动生成的查询生成器
-
支持多个数据库。在 SQL 和 NoSQL 数据库之间移动时,这对开发人员来说是一个巨大的优势,因为只需要更改 Schema 文件。所有其他操作/查询保持不变。
-
支持多个 RDBMS
-
Prisma 允许您根据标准过滤列表,该标准不仅适用于正在检索的列表的模型,而且适用于该模型的关系。 Mongoose 没有为关系过滤器提供专用的 API。您可以通过添加额外的步骤来过滤查询返回的结果来获得类似的功能。
-
Prisma Studio有助于轻松管理数据的工具。
Prisma的缺点
另一方面,与 Mongoose 相比,Prisma 也有一些缺点。
-
不支持多个模型文件。所有模型都需要写入
schema.prisma
文件,这使得文件杂乱无章,难以调试和阅读。 -
Prisma MongoDB 支持目前处于预览阶段
-
目前没有嵌入式集合支持。
-
错误处理不完整。
-
当前不支持迁移和自省工作流。
-
目前不支持
@@id
和自增。
你应该在 Mongoose 上使用 Prisma 吗?
Prisma 是一种现代的 ORM,它有自己的权衡取舍。如果您正在使用 REST API 和 GraphQL 构建服务器端应用程序,那么 Prisma 将是一个不错的选择。它还使开发人员的生活更轻松。 Prisma 为最常见的数据库工作流程显着提高了生产力。
如果这些因素对您来说并不重要,并且您希望更好地控制数据库操作,那么我的建议是“暂时”使用 Mongoose。
为 Prisma 做贡献
Prisma MongoDB 连接器仍处于预览和开发阶段。如果您想为 Prisma 做出贡献,请单击此处的查看他们的 GitHub 存储库。
更多推荐
所有评论(0)