基于 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 副本集之门。
相关推荐
丶21366 分钟前
【Nginx】在 Docker 上安装 Nginx 的详细指南
运维·nginx·docker
小白小白从不日白7 分钟前
react hooks--useReducer
前端·javascript·react.js
下雪天的夏风19 分钟前
TS - tsconfig.json 和 tsconfig.node.json 的关系,如何在TS 中使用 JS 不报错
前端·javascript·typescript
diygwcom31 分钟前
electron-updater实现electron全量版本更新
前端·javascript·electron
wn53135 分钟前
【Go - 类型断言】
服务器·开发语言·后端·golang
Hello-Mr.Wang1 小时前
vue3中开发引导页的方法
开发语言·前端·javascript
希冀1231 小时前
【操作系统】1.2操作系统的发展与分类
后端
程序员凡尘1 小时前
完美解决 Array 方法 (map/filter/reduce) 不按预期工作 的正确解决方法,亲测有效!!!
前端·javascript·vue.js
GoppViper1 小时前
golang学习笔记29——golang 中如何将 GitHub 最新提交的版本设置为 v1.0.0
笔记·git·后端·学习·golang·github·源代码管理
爱上语文2 小时前
Springboot的三层架构
java·开发语言·spring boot·后端·spring