Prisma,有喜有愁?...

我们项目主要使用的是 mongodb ,目前使用的 ORM 框架是 TypeORM。但是 TypeORM 的更新速度和对于 MongoDB 的支持实在感觉有点难受,于是之前抽空尝试了一下火热的 Prisma,写了一套 CURD 之后感觉有些五味杂陈...

Prisma 诸如类型安全,Prisma Studio 等等新功能可以阅读社区中的文章了解,本文还是想写出一些略微不便之处。

Prisma 与 TypeORM 的对比可以参考:

  1. prisma.yoga/concepts/mo...
  2. juejin.cn/post/732320...

仓库 issues 回应速度较慢

将这个问题写在第一是因为下面列出的所有问题我都在 issue 中查找到了社区反馈,但是始终没有官方的解决方案。issue open 时间极其长,feedback 不断叠加。

Mongodb 需要使用副本集模式

www.prisma.io/docs/orm/ov...

对于 Mongodb sharding 模式我没有进行实际测试,仅依靠 issue 描述进行判断,可能至当前版本时已经支持。

github.com/prisma/pris... github.com/prisma/pris...

Prisma 如果不将 MongoDB 配置为副本集模式,在运行 prisma gengrate 时会提示

text 复制代码
Transactions are not supported by this deployment

我在开发过程中通常是通过 docker 创建一个独立的 mongodb,在 docker mongodb 中创建副本集的命令是

shell 复制代码
docker run --name mongodb -d -p 27017:27017 mongo:latest mongod --replSet rs0
docker exec -d mongodb mongosh --eval \
    "rs.initiate({_id: 'rs', members: [{_id: 0, host: 'localhost:27017'}]})"

在生产环境中,配置副本集链接字符串有两种方法:

  1. 将副本集中的所有节点都写入链接字符串中
text 复制代码
mongodb+srv://username:password@host1,host2,host3/mydatabase?replicaSet=myReplicaSetName

将所有节点都写入会造成链接字符串极其长,可维护性变差

  1. 使用 mongodb+srv 方式进行链接
text 复制代码
mongodb+srv://username:password@your-cluster-hostname/databaseName?replicaSet=yourReplicaSetName

使用 DNS SRV 记录可能需要自行维护记录解析的变更,并且在记录变更后由于 DNS 解析缓存的原因也可能造成无法及时切换。

schema.prisma 文件无法拆分,所有的模型 All in one

github.com/prisma/pris...

Prisma 需要在 schema.prisma 中声明 client-provier 和 datasouce 以及各种模型,Prisma 只会读取一个单一的 xx.prisma 文件。假如项目中存在多个数据表,可以预想到文件的行数会变得极其长,在一个极其长的文件中上下滑动寻找表结构并修改的体验我觉得并不是很好。

反观 TypeORM 为单独定义 Entity 并手动导入使用,倒也就可以单独对某个表进行修改,并且在 git diff 时也很好观察。

社区也有了一些解决方法,有自行实现了 export import 关键字的,也有通过编辑器插件实现注释大纲的。我最后选择了 export & import 方案。

  1. 编辑器插件实现注释大纲

github.com/prisma/pris...

github.com/akirarika/c...

好处是侵入性小,只需要安装一个独立的 vscode 插件即可,不影响官方的编辑器插件

  1. prisma-import

github.com/ajmnz/prism...

可以将每个 model 都拆分到不同的 .prisma 文件中,通过 import 关键字导入。目录结构可以如下所示:

text 复制代码
prisma
 ├── schema.prisma
 └── src
     ├── index.prisma
     └── model
         ├── comment.model.prisma
         ├── post.model.prisma
         └── user.model.prisma

schema.prismaprisma-import 最终会覆写的文件,不应在此文件中手动书写任何配置。

index.prisma 文件中包含了 client-provider、datasouce 等全局配置,以及每个 model 的 import

prisma 复制代码
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
}

import { User } from "model/user.model"
import { Post } from "model/post.model"
import { Comment } from "model/comment.model"

*.model.prisma 文件中按照官方语法定义 model 即可,如果有需要进行关联的表也可以通过 import 导入。

prisma 复制代码
import { Post } from "./post.model"

model User {
  id      String   @id @default(auto()) @map("_id") @db.ObjectId
  email   String   @unique
  name    String
  address Address?
  posts   Post[]
}

type Address {
  street String
  city   String
  state  String
  zip    Int
}

最终通过 cli 命令进行覆写即可

shell 复制代码
prisma-import --force --schemas prisma/src/index.prisma --schemas prisma/src/model/*

覆写后的 schema.prisma 文件如下:

prisma 复制代码
//
// Autogenerated by `prisma-import`
// Any modifications will be overwritten on subsequent runs.
//

//
// index.prisma
//

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mongodb"
  url      = env("DATABASE_URL")
}

//
// comment.model.prisma
//

model Comment {
  id      String @id @default(auto()) @map("_id") @db.ObjectId
  comment String
  post    Post   @relation(fields: [postId], references: [id])
  postId  String @db.ObjectId
}

但这与官方的语法相悖,使用官方的编辑器插件高亮会各种飘红。prisma-import 作者只开发了 vscode 的编辑器插件,Webstorm 的体验感相对较差。并且需要禁用官方的编辑器插件以避免冲突,如果之后官方支持了新的语法或关键字可能插件不能及时支持。

  • WebStorm
  • VSCode

findAndCount 没有官方的支持,需要安装插件

github.com/prisma/pris...

可以通过安装插件或手动运行 count 查询实现相同的效果。

我翻了一下 typeorm 的源码,发现他们也是同时运行 find & count 实现的 findAndCount

  • 使用插件

github.com/deptyped/pr...

插件可以支持普通的 offset & limit 分页和游标分页。

typescript 复制代码
import { pagination } from 'prisma-extension-pagination';

new PrismaClient({
  datasourceUrl: env.DATABASE_URL,
  log: [{ level: 'query', emit: 'event' }],
}).$extends(pagination())

findAndCount 中可以解构出 meta

typescript 复制代码
const [users, meta] = await prisma.user.paginate().withPages({
  page,
  limit: pageSize,
  includePageCount: true,
});

return ({
    pagination: {
      page: meta.currentPage,
      pageSize,
      total: meta.totalCount,
      pageCount: meta.pageCount,
    }
})

最后叠个甲

本文主要记录对于 Prisma 的一些不便之处以及对应的解决方法,其中有些问题只通过阅读 issue,没有实际搭建环境测试,可能存在错误。如果有更好的解决方法或文中存在错误,敬请指正,谢谢(鞠躬)

相关推荐
Σίσυφος190020 分钟前
halcon 条形码、二维码识别、opencv识别
前端·数据库
学代码的小前端22 分钟前
0基础学前端-----CSS DAY13
前端·css
bing_1581 小时前
简单工厂模式 (Simple Factory Pattern) 在Spring Boot 中的应用
spring boot·后端·简单工厂模式
css趣多多2 小时前
案例自定义tabBar
前端
天上掉下来个程小白2 小时前
案例-14.文件上传-简介
数据库·spring boot·后端·mybatis·状态模式
Asthenia04122 小时前
基于Jackson注解的JSON工具封装与Redis集成实战
后端
编程星空3 小时前
css主题色修改后会多出一个css吗?css怎么定义变量?
开发语言·后端·rust
姑苏洛言3 小时前
DeepSeek写微信转盘小程序需求文档,这不比产品经理强?
前端
林的快手3 小时前
CSS列表属性
前端·javascript·css·ajax·firefox·html5·safari
程序员侠客行3 小时前
Spring事务原理 二
java·后端·spring