一、why?
如果要使用 Primsa ORM
操作 MongoDB
那么必须要上 MongoDB
的副本集,官方给出的解释是需要支持 事务
。下面会基于 docker/docker-compose
快速的创建一个副本集,然后使用 Prisma ORM
完成基本的 CURD/List/Count
操作。
注意:本文主旨是打通 TS/JS 构建副本集环境,数据库安全问题需要另外考虑的。阅读本文需要 docker/docker-compose/PrismaORM/Node.js/NestJS 等相关基础。
二、docker-compose 相关
推荐使用 docker-compose 客户端
1)docker-compose 编排
编排使用最简单的: 1 主, 2 从,3 投票
的方式。
yaml
version: '3'
services:
mongodb-primary:
image: mongo:latest
container_name: mongodb-primary
ports:
- '27017:27017'
command: mongod --replSet rs0
networks:
- my-network
mongodb-secondary:
image: mongo:latest
container_name: mongodb-secondary
depends_on:
- mongodb-primary
command: mongod --replSet rs0
networks:
- my-network
mongodb-arbiter:
image: mongo:latest
container_name: mongodb-arbiter
depends_on:
- mongodb-primary
command: mongod --replSet rs0 --oplogSize 128
networks:
- my-network
networks:
my-network:
driver: bridge
主应用对外暴露 27017
的端口。
2)初始化集群
进入 mongodb-primary 容器中, 输入 mongosh,进入 MongoDB 提供的 shell 工具,执行如下命令
ts
_id: 'rs0',
members: [
{ _id: 0, host: 'mongodb-primary:27017' },
{ _id: 1, host: 'mongodb-secondary:27017' },
{ _id: 2, host: 'mongodb-arbiter:27017' },
],
});
如果一切正常,副本集就正常启动了。可以访问 主
来查看服务是否正常启动
2)运行与停止
sh
docker-compose up -d # 默认docker-compose 文件
docker-compose down # 移除
3)VSCode 中链接 MongoDB
VS Code 中 安装插件
提供了两种链接方式:
- 字符串链接
sh
mongodb://localhost:27017/test_db?readPreference=primary&ssl=false&directConnection=true
# 注意:此处用没有创建用户的 test_db 进行登录,实际中需要注意数据库安全
- 增强链接
增强的更加方便了,直接输入表单中的数据即可。
三、在 Prisma 中使用 mongoDB 集群
1) 安装依赖
sh
pnpm add prisma @prisma/client
2) 初始化
sh
pnpx primsa init
生成:
env
环境变量(待会需要修改) -/prisma/prisma.schema
的schema
文件(根据自己的需求改)
3) 生成客户端
sh
pnpx prisma generate
4) pnpm 中添加前置脚本
sh
{
"scripts": {
"postinstall": "npm prisma generate"
}
}
添加了前置脚本就会每次执行了 pnpm add
/pnpm i
命令之后重新只执行 ,在部署的时候非常有用。
5) 修改 prisma.schema 并定义 User 文件
以下是一个示例:
prisma
generator client {
provider = "prisma-client-js"
output = "../node_modules/.prisma"
}
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
model User {
id String @id @default(auto()) @map("_id") @db.ObjectId
username String
password String
email String @unique
role String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
- 指定了
Primsa ORM
客户端的生成地址在../node_modules
中(使用 pnpm workspace) 推荐修改 - 指定了
MongoDB
数据库 - 指修改
.env
环境变量自定为MongoDB
集群地址
sh
DATABASE_URL="mongodb://localhost:27017/test_db?readPreference=primary&ssl=false&directConnection=true"
在修改完毕之后重新生成 Primsa ORM
客户端, 生成新客户端。
ts
pnpx prisma generate
四、在 NestJS Service 中提供 CRUD/List/Count 服务
引用客户端和 shema 提供的类型。
ts
import { PrismaClient, User } from '@@prisma'; // 在 tsconfig.json 中配置
@@prisma
:pnpm workspace
中运行,所以被重置了地址,为什么需要重置?
因为 pnpm workspace
生成客户端时,都会在 root node_modules
中生成,且会冲突,需要每一个 Prisma ORM
保持单独性,所以需要重置。
ts
// prisma.service.ts
import { Injectable } from '@nestjs/common';
import { PrismaClient, User } from '@@prisma'; // 在 tsconfig.json 中配置
@Injectable()
export class PrismaService {
private prisma: PrismaClient;
constructor() {
this.prisma = new PrismaClient();
}
async createUser({
username,
password,
email,
role,
}}): Promise<User> {
return this.prisma.user.create({
data: {
username,
password,
email,
role,
},
});
}
async updateUser({
id,
password,
}): Promise<User | null> {
return this.prisma.user.update({
where: { id },
data: {
password,
},
});
}
async deleteUser(id: string): Promise<User | null> {
return this.prisma.user.delete({
where: { id },
});
}
async getUserById(id: string): Promise<User | null> {
return this.prisma.user.findUnique({
where: { id },
});
}
async getList({
page,
pageSize,
}: {
page: number;
pageSize: number;
}): Promise<User[]> {
const skip = (page - 1) * pageSize;
return this.prisma.user.findMany({
skip,
take: pageSize,
});
}
async getUsersCount(): Promise<number> {
return this.prisma.user.count();
}
}
以上是基于 Primsa ORM
对于 MongoDB
的基本厂常见的增删改业务。
六、小结
- 本文主要讲解了使用
docker-compose
入门级编排基本的MongoDB
副本集(使用时需要注意数据库安全,本文是案例)。其次是实践,使用Prisma ORM
+NestJS
来操作数据库。希望能帮读者打通MongoDB
副本集之门。