最近几个月在学习鸿蒙知识时需要使用 mongodb,考虑到来回奔波于家和公司之间需要给不同的设备安装 mongodb 来使用,因而选择在服务器上创建 mongodb 容器来解决这个问题

基本使用

创建本地持久存储目录

在文件夹下创建 data、logs、dump 文件夹,在创建 mongodb 容器时进行挂载

1
mkdir data logs confg dump
  • data 持久化存储的数据文件夹
  • logs 日志文件夹
  • dump 备份文件夹

一行命令启动容器

1
2
3
4
5
6
7
8
9
docker run -it \
--name mongodb \
--restart=always \
--privileged \
-p 27017:27017 \
-v /docker/mongo/data:/data/db \
-v /docker/mongo/dump:/data/dump \
-v /docker/mongo/logs:/data/log \
-d mongo:latest
  • --name 指定容器名
  • --restart=always 自动重新启动
  • --privileged 允许容器以特权模式运行
  • -p 27017:27017 指定运行端口
  • -v 挂载上面创建的持久化文件夹
  • -d 后台运行容器

使用 nest 连接 mongodb

创建 nest 项目

nest new project-name 创建项目

1
nest new nest-mongodb

安装连接 mongodb 数据库的依赖包

1
pnpm add @nestjs/mongoose mongoose

在 app.modules.ts 中添加数据库配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose';
import { BannerSchema, MenuSchema } from './schemas';

@Module({
imports: [
//连接mongodb数据库
MongooseModule.forRoot('mongodb://10.10.48.108/mongo'),
//配置mongose模型
MongooseModule.forFeature([
{
name: 'Banner',
schema: BannerSchema,
},
{
name: 'Menu',
schema: MenuSchema,
},
]),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

pnpm:start:dev 启动 nest 项目后,通过 MongoDB for VS Code 插件连接启动的 mongodb 容器,就可以看到对应的 banner 和 menu 表了

测试 mongodb

修改 app.controller.ts 文件,创建一个 get 请求使的访问 127.0.0.1 返回查询 banner 表的数据,和一个 post 请求,可以给 banner 表中添加数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { Controller, Get, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';
import { Banner, HttpResponse } from './types';

@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}

@Get()
async getBanners(): Promise<HttpResponse<Banner[]>> {
const data = await this.appService.find();
if (data) {
return {
code: 1,
message: '请求成功',
data,
};
}
}
@Post()
async addBanner(
@Body() addBannerDTO: Banner | Banner[],
): Promise<HttpResponse> {
const data = await this.appService.add(addBannerDTO);
if (data) {
return {
code: 1,
message: '添加成功',
};
}
}
}

修改 app.service.ts 文件,创建一个 find 查询方法和一个 inset 插入方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Banner } from './types';
@Injectable()
export class AppService {
constructor(@InjectModel('Banner') private bannerModel: Model<Banner>) {}
async find(): Promise<Banner[]> {
const data = await this.bannerModel.find().exec();
return data;
}
async add(addBannerDTO: Banner | Banner[]): Promise<Banner | Banner[]> {
if (Array.isArray(addBannerDTO)) {
const data = await this.bannerModel.insertMany(addBannerDTO);
return data;
} else {
const data = await new this.bannerModel(addBannerDTO).save();
return data;
}
}
}

使用 postman 测试 get 请求

通过 post 接口给数据库添加数据

可以在数据库中看到添加的数据

给 mongodb 添加权限

上述内容已经满足了我们日常本地开发的需要,但部署在服务器上的话,因为没有给 mongodb 添加权限会导致任何人都可以读写数据库,存在很大的安全风险,因而需要添加权限来使用

1
2
3
4
5
6
7
8
9
10
11
# 启动容器时,添加--auth命令
docker run -it \
--name mongodb \
--restart=always \
--privileged \
-p 27017:27017 \
-v /docker/mongo/data:/data/db \
-v /docker/mongo/dump:/data/dump \
-v /docker/mongo/logs:/data/log \
-d mongo:latest \
--auth

开启后重新 get 请求,在命令行中会提示需要授权才可以访问

添加 mongo 表用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 进入容器
docker exec -ti 容器id /bin/bash
# mongosh进入数据库
mongosh
# 先在admin中创建root用户
use admin
# 创建root用户
db.createUser({user:"root",pwd:"root123",roles:["root"]})

# 授权admin
db.auth("root","root1234")

# 创建mongo表用户
use mongo
db.createUser({user:"mongo",pwd:"mongo123",roles:[{role:"readWrite",db:"mongo"}]})

然后在 MongoDB for VS Code 新建连接,使用 mongodb://mongo:mongo123@10.10.48.108:27017/mongo 连接就可以正常使用了

再修改 nest 中连接 mongodb 的配置为 mongodb://mongo:mongo123@10.10.48.108:27017/mongo,请求也可以正常使用了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose';
import { BannerSchema, MenuSchema } from './schemas';

@Module({
imports: [
//配置mongose模型
MongooseModule.forRoot('mongodb://mongo:mongo123@10.10.48.108:27017/mongo'),
MongooseModule.forFeature([
{
name: 'Banner',
schema: BannerSchema,
},
{
name: 'Menu',
schema: MenuSchema,
},
]),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}