基于 docker-compose 适用于 TS/JS 开发者的 mongoDB 副本集入门及实践

一、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.schemaschema 文件(根据自己的需求改)

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 中配置

@@prismapnpm 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 副本集之门。
相关推荐
星星在线1 小时前
MusicFree:一个「All in One」的个人音乐服务器,让听歌回归简单
前端·后端
IT_陈寒2 小时前
Redis的SETNX并发问题让我加了三天班
前端·人工智能·后端
demo007x2 小时前
Docling 文档转换以及技术架构分析
前端·后端·程序员
京东云开发者3 小时前
京东市民服务又“上新”!这次是黑龙江“龙易办”
前端
袋鱼不重3 小时前
我的神奇同事,AI 用多了居然写了个 Open In Codex
前端·后端·ai编程
用户8356290780513 小时前
使用 Python 操作 Word 内容控件
后端·python
像我这样帅的人丶你还3 小时前
啥? 前端也要会干Java?🛵🛵🛵
后端
Hommy884 小时前
【剪映小助手】添加贴纸接口(Add Sticker)
后端·github·剪映小助手·视频剪辑自动化·剪映api
Fireworks4 小时前
深入vue3源码解读 -- 1、响应式的基础概念
前端
程序员黑豆4 小时前
JDK 下载安装与配置详细教程
java·前端·ai编程