[TOC]


基本信息

MongoDB 是一个 开源的 NoSQL 数据库,用 JSON 风格的文档来存储数据,而不是传统关系型数据库的表和行。


主要特点

  1. 文档型存储

    • 数据以 BSON(二进制 JSON)格式保存,类似:

      1
      2
      3
      4
      5
      {
      "name": "Alice",
      "age": 25,
      "skills": ["Python", "Vue"]
      }
  2. 无固定模式(Schema-less)

    • 同一个集合(collection)里的文档结构可以不同,方便灵活扩展。
  3. 高扩展性

    • 支持 分片(Sharding)副本集(Replica Set),可以水平扩展和高可用。
  4. 查询功能强大

    • 支持丰富的查询语法、聚合管道(Aggregation Pipeline)、地理位置查询等。
  5. 适合大数据和快速开发

    • 常用于日志存储、实时分析、内容管理、物联网等场景。

基本概念对比(与 MySQL 类比)

MySQL MongoDB
数据库 (Database) 数据库 (Database)
表 (Table) 集合 (Collection)
行 (Row) 文档 (Document)
列 (Column) 字段 (Field)

简单操作示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 连接 MongoDB
mongo

# 切换/创建数据库
use mydb

# 插入数据
db.users.insert({name: "Alice", age: 25})

# 查询数据
db.users.find({age: {$gt: 20}})

# 更新数据
db.users.update({name: "Alice"}, {$set: {age: 26}})

# 删除数据
db.users.remove({name: "Alice"})

我给你按清单的方式整理一下 MongoDB 的 优缺点应用场景,方便快速理解。


MongoDB 的 优缺点应用场景

优点

  1. 灵活的数据结构
    • 无需预先定义字段结构,适应需求变化快的项目。
  2. 文档型存储,直观易读
    • 数据以 JSON/BSON 格式保存,前后端交互方便。
  3. 高可扩展性
    • 分片(Sharding)支持水平扩展,适合海量数据。
  4. 高可用性
    • 副本集(Replica Set)保证数据冗余和自动故障切换。
  5. 查询和聚合功能强
    • 内置复杂查询、索引、聚合管道,数据处理灵活。
  6. 开发效率高
    • 无需繁琐的表设计,数据结构变动无需迁移表结构。

缺点

  1. 事务支持不如关系型数据库
    • 虽然 4.0 以后支持多文档事务,但性能不如 MySQL。
  2. 数据占用空间较大
    • BSON 比 JSON 更占空间,存储成本可能增加。
  3. 过度灵活可能导致数据不规范
    • 如果不做好约束,容易出现字段不统一、数据混乱。
  4. 复杂关联查询性能差
    • 不擅长多表(多集合)复杂 JOIN。
  5. 内存占用高
    • 需要较多内存来保证索引和性能。

典型应用场景

  1. 内容管理系统(CMS)
    • 博客、新闻、产品展示网站等,数据结构灵活多变。
  2. 大数据实时分析
    • 日志系统、行为数据分析(如 ELK 替代方案)。
  3. 物联网(IoT)数据存储
    • 设备上传的数据格式不统一,适合文档型存储。
  4. 地理位置应用
    • 位置检索(附近的人、附近的店)。
  5. 电商平台
    • 商品信息多样、字段不固定(不同商品有不同属性)。
  6. 游戏后台
    • 玩家数据、装备、日志等非结构化数据。
  7. 社交平台
    • 用户动态、评论、消息等。

我建议如果你要存储 结构多变、读写频繁、数据量大 的内容,MongoDB 很合适;
如果你要 事务性强、结构固定、数据关系复杂,MySQL 会更好。


如果你需要,我可以帮你做一份 MongoDB vs MySQL 应用场景对比表,这样你一眼就能判断该用哪个。

docker部署

准备工作

准备配置文件与目录结构

image-20250815162323252

./conf/mongod.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
storage:
dbPath: /data/db

systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log

net:
port: 27017
bindIp: 0.0.0.0

processManagement:
fork: false
timeZoneInfo: /usr/share/zoneinfo

security:
authorization: enabled

运行 MongoDB 容器

1
2
3
4
5
6
7
8
9
10
11
docker run -d \
--name mongodb \
-p 27017:27017 \
-v /data/soft/mongo/mongo-1/data:/data/db \
-v /data/soft/mongo/mongo-1/conf/mongod.conf:/etc/mongod.conf \
-v /data/soft/mongo/mongo-1/logs:/var/log/mongodb \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=123456 \
-e TZ=Asia/Shanghai
mongo:latest \
--config /etc/mongod.conf

参数说明:

  • --name mongodb:容器名称
  • -p 27017:27017:映射端口
  • -v /root/mongo/data:/data/db:持久化数据到宿主机
  • -e MONGO_INITDB_ROOT_USERNAME:管理员用户名
  • -e MONGO_INITDB_ROOT_PASSWORD:管理员密码
  • mongo:latest:镜像名

验证容器运行

1
docker ps

image-20250815162957335


连接 MongoDB

进入容器:

1
docker exec -it mongodb mongosh -u admin -p 123456

或者在宿主机直接用客户端连接:

1
mongodb://admin:123456@<宿主机IP>:27017

使用python测试

需要安装 pymongo库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from pymongo import MongoClient

# 构造连接字符串
uri = "mongodb://admin:123456@192.168.72.11:27017/mydb?authSource=admin"

# 创建客户端
client = MongoClient(uri)

# 选择数据库
db = client["regendb"]

# 选择集合
users = db["users"]

# 查询全部
for user in users.find():
print(user)

# 插入一条数据
users.insert_one({"name": "regen", "age": 25})

# 查询一条数据
print(users.find_one({"name": "Alice"}))

image-20250815164942223

一键安装脚本

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/bin/bash
set -e

# =========================
# Docker 安装 MongoDB 7.0.6 脚本
# =========================
#
# 脚本功能:
# 1. 尝试 Docker 拉取 MongoDB 7.0.6 镜像
# 2. 尝试导入本地镜像(mongo7.0.6.tar)
# 3. 创建数据、配置、日志目录,并设置权限
# 4. 生成默认配置文件 mongod.conf
# 5. 启动 MongoDB 容器,并设置管理员账号密码、端口、时区
# 6. 检查容器是否成功启动
#
# 适用场景:
# - 无网络环境下使用 Docker 安装 MongoDB 7.0.6
# - 需要快速部署 MongoDB 7.0.6 容器,并支持外部访问
#
# 可配置变量:
# IMAGE_FILE MongoDB 镜像 tar 包路径
# IMAGE_NAME Docker 镜像名称
# CONTAINER_NAME 容器名称
# MONGO_PORT MongoDB 端口
# MONGO_USER 管理员用户名
# MONGO_PASSWORD 管理员密码
# TZ 容器时区
# BASE_DIR 数据、配置、日志基础目录
#
# 使用方法:
# 1. 确保 /resources/mongo7.0.6.tar 文件存在
# 2. 执行脚本:sudo bash /scripts/local-docker-mongo.sh
# 3. 查看容器状态:docker ps
# 4. 查看日志:docker logs $CONTAINER_NAME



# =========================
# 可配置参数
# =========================
IMAGE_FILE="/resources/mongo7.0.6.tar"
IMAGE_NAME="mongo:7.0.6"
CONTAINER_NAME="mongodb"
MONGO_PORT=27017
MONGO_USER="admin"
MONGO_PASSWORD="Z3ACxCMS"
TZ="Asia/Shanghai"

# 数据、配置、日志目录
BASE_DIR="/data/soft/mongo"
DATA_DIR="$BASE_DIR/data"
CONF_DIR="$BASE_DIR/conf"
LOGS_DIR="$BASE_DIR/logs"

# =========================
# 创建目录结构
# =========================
echo "创建目录..."
mkdir -p "$DATA_DIR" "$CONF_DIR" "$LOGS_DIR"
# 设置日志目录权限,保证容器可写
chown -R 999:999 "$LOGS_DIR"

if docker pull "$IMAGE_NAME"; then
echo "镜像 $IMAGE_NAME 拉取成功,跳过导入"
else
echo "镜像 $IMAGE_NAME 拉取失败,尝试导入本地镜像 $IMAGE_FILE ..."
if docker image inspect "$IMAGE_NAME" >/dev/null 2>&1; then
echo "镜像 $IMAGE_NAME 已存在,跳过导入"
else
LOADED_IMAGE=$(docker load -i "$IMAGE_FILE" | awk -F': ' '/Loaded image:/ {print $2}')
echo "加载完成,原始镜像: $LOADED_IMAGE"

docker tag "$LOADED_IMAGE" "$IMAGE_NAME"
echo "镜像已重命名为 $IMAGE_NAME"
fi
fi

# =========================
# 创建默认配置文件
# =========================
CONF_FILE="$CONF_DIR/mongod.conf"
echo "创建默认配置文件 $CONF_FILE ..."
cat > "$CONF_FILE" <<EOF
storage:
dbPath: /data/db

systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log

net:
port: $MONGO_PORT
bindIp: 0.0.0.0

processManagement:
fork: false
timeZoneInfo: /usr/share/zoneinfo

security:
authorization: enabled
EOF


# =========================
# 启动容器
# =========================
echo "启动 MongoDB 容器..."
CONTAINER_ID=$(docker run -d \
--name "$CONTAINER_NAME" \
--restart=unless-stopped \
-p $MONGO_PORT:27017 \
-v "$DATA_DIR":/data/db \
-v "$CONF_FILE":/etc/mongod.conf \
-v "$LOGS_DIR":/var/log/mongodb \
-e MONGO_INITDB_ROOT_USERNAME="$MONGO_USER" \
-e MONGO_INITDB_ROOT_PASSWORD="$MONGO_PASSWORD" \
-e TZ="$TZ" \
$IMAGE_NAME \
--config /etc/mongod.conf) || {
echo "容器启动失败!请检查配置或镜像"
exit 1
}

# =========================
# 检查容器状态
# =========================
if [ "$(docker ps -q -f id=$CONTAINER_ID)" ]; then
echo "MongoDB 容器已启动,容器名:$CONTAINER_NAME"
docker ps --filter "id=$CONTAINER_ID"
else
echo "MongoDB 容器启动失败,请查看日志:docker logs $CONTAINER_NAME"
exit 1
fi

宿主机安装

包管理器安装

1
sudo dnf install -y mongodb-org

离线包安装

准备好离线包

1
2
# 在有网的机器下载
dnf download --resolve mongodb-org

scp或者xftp复制到某个文件夹后

1
dnf install -y ./*.rpm

配置文件(可选)

修改端口绑定

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
34
35
36
37
38
39
40
41
42
43
# mongod.conf

# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/

# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log

# Where and how to store data.
storage:
dbPath: /var/lib/mongo
journal:
enabled: true
# engine:
# wiredTiger:

# how the process runs
processManagement:
timeZoneInfo: /usr/share/zoneinfo

# network interfaces
net:
port: 27017
bindIp: 0.0.0.0


#security:

#operationProfiling:

#replication:

#sharding:

## Enterprise-Only Options

#auditLog:

#snmp:

启动

1
2
3
4
sudo systemctl start mongod
sudo systemctl enable mongod
sudo systemctl status mongod

初始化

1
2
3
4
5
6
7
mongosh
use admin
db.createUser({
user: "admin",
pwd: "123456",
roles: [ { role: "root", db: "admin" } ]
})

一键安装脚本

需要提前准备好安装包到对应的目录。

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/bin/bash


# ============================
# MongoDB 离线安装脚本
# ============================
#
# 脚本功能:
# 1. 离线安装 MongoDB RPM 包
# 2. 自动生成或修改默认配置文件
# 3. 修改 bindIp 为 0.0.0.0,使外部可访问
# 4. 创建数据目录和日志目录,并设置权限
# 5. 启动 MongoDB 服务并启用开机自启
# 6. 创建管理员账号及密码
#
# 适用场景:
# - 无网络环境下,需要离线安装 MongoDB
# - Linux 系统使用 DNF/YUM 包管理的环境(如 CentOS 8 / RHEL 8 / Fedora)
#
# 前置条件:
# - 已将 MongoDB RPM 包放在 /data/resources/mongo 目录
# - 有 sudo 权限
#

# 注意事项:
# - 如果管理员账号已存在,会报错
# - 数据目录默认 /var/lib/mongo,日志目录默认 /var/log/mongodb
# - 可根据需要修改端口和管理员账号密码变量
#
# 使用方法:
# 1. 将脚本放在任意目录,例如 /scripts/local-install-mongo.sh
# 2. 修改顶部变量 MONGO_RPM_DIR、ADMIN_USER、ADMIN_PASS、PORT
# 3. 执行:sudo bash /scripts/local-install-mongo.sh

set -e

# 配置变量
MONGO_RPM_DIR="/data/resources/mongo"
CONF_FILE="/etc/mongod.conf"
ADMIN_USER="admin"
ADMIN_PASS="123456"
PORT=27017

echo "==========================="
echo "MongoDB 离线安装脚本-开始"
echo "==========================="

# 1️⃣ 安装 RPM 包
echo "安装 MongoDB RPM 包..."
sudo dnf install -y $MONGO_RPM_DIR/*.rpm

# 2️⃣ 修改配置文件
echo "配置 mongod.conf..."
if [ ! -f "$CONF_FILE" ]; then
echo "mongod.conf 不存在,创建默认配置..."
cat > "$CONF_FILE" <<EOF
storage:
dbPath: /var/lib/mongo

systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log

net:
port: $PORT
bindIp: 127.0.0.1

processManagement:
fork: true
timeZoneInfo: /usr/share/zoneinfo

security:
authorization: enabled
EOF
fi

# 修改 bindIp 为 0.0.0.0
sed -i "s/bindIp:.*/bindIp: 0.0.0.0/" "$CONF_FILE"

# 3️⃣ 确保数据目录和日志目录存在且权限正确
DATA_DIR=$(grep 'dbPath' $CONF_FILE | awk '{print $2}')
LOG_FILE=$(grep 'path:' $CONF_FILE | grep mongodb | awk '{print $2}')
LOG_DIR=$(dirname "$LOG_FILE")

mkdir -p "$DATA_DIR" "$LOG_DIR"
chown -R mongod:mongod "$DATA_DIR" "$LOG_DIR"
chmod 700 "$DATA_DIR"
chmod 755 "$LOG_DIR"

# 4️⃣ 启动 MongoDB 服务
echo "启动 MongoDB..."
sudo systemctl enable mongod
sudo systemctl start mongod

# 等待服务启动
sleep 5

# 5️⃣ 创建管理员账号
echo "创建管理员账号 $ADMIN_USER..."
mongo --eval "db.getSiblingDB('admin').createUser({user: '$ADMIN_USER', pwd: '$ADMIN_PASS', roles:[{role:'root', db:'admin'}]});"

echo "MongoDB 安装完成,管理员账号: $ADMIN_USER 密码: $ADMIN_PASS"
echo "默认端口: $PORT, 监听所有 IP: 0.0.0.0"
echo "可以使用: sudo systemctl status mongod 查看服务状态"

image-20250815164416267

image-20250815164358826

数据备份与恢复

mongo数据库备份分析

1. 早期版本 (MongoDB 2.x~3.6)

  • 用户信息可以存储在每个数据库内部,也就是 db.system.users
  • 用户只对所在数据库有权限。
  • 认证数据库默认就是用户所在数据库。

例如:

1
2
use test
db.createUser({user: "alice", pwd: "123", roles: ["readWrite"]})

这时用户 alice 存储在 test.system.users


2. 现代版本 (MongoDB 4.x~7.x)

  • 用户统一存储在 admin 数据库中(默认)。
  • MongoDB 使用 “全局用户认证机制”,所有用户和角色信息集中存储在 admin.system.users
  • 这样管理更集中、权限更统一,也便于跨数据库授权。

例如:

1
2
use admin
db.createUser({user: "admin", pwd: "123", roles: ["root"]})

然后可以给其他数据库授予权限,不必在每个数据库中单独创建用户。


早期版本备份用户:

1
mongodump --db test --collection system.users --out /tmp/backup

恢复:

1
2
mongorestore --db test --collection system.users /tmp/backup/test/system.users.bson

全备份示例

1
2
3
4
5
# 创建备份目录
mkdir -p /tmp/backup

# 导出所有数据库
mongodump -u admin --password 123456 --authenticationDatabase admin --out /tmp/backup
  • 默认会连接本地 27017
  • 所有数据库会导出到 /tmp/backup,每个数据库生成一个文件夹,每个集合生成 .bson.metadata.json 文件。

备份单个数据库

1
2
# 导出所有数据库
mongodump -u admin -p 123456 --authenticationDatabase admin -d regen --out /tmp/backup

容器外备份(宿主机访问容器 MongoDB)

如果你在宿主机操作,假设容器映射端口 27017:

1
2
3
mkdir -p /root/mongo_backup

mongodump -h 127.0.0.1 -p 27017 -u admin --password 123456 --authenticationDatabase admin --out /tmp/backup
  • /tmp/backup → 宿主机存储路径
  • 会生成类似:
1
2
3
4
5
6
/root/mongo_backup/
├── admin/
├── config/
├── local/
├── mydb/
└── otherdb/

还原所有数据库

也包括之前的用户认证信息。

如果要恢复全部数据库:

1
mongorestore -u admin --password 123456 --authenticationDatabase admin /root/backup
  • 可以加 --drop 选项覆盖已有数据库:
1
mongorestore --drop -u admin --password 123456 --authenticationDatabase admin /root/backup
  • 导出单个数据库--db mydb
  • 导出全部数据库 → 不加 --db
  • 容器内操作简单,容器外操作需要指定 host/port
  • 挂载宿主机目录可以持久化备份

mongo基础


1. 数据库相关

功能 命令
显示所有数据库 show dbs
切换数据库(不存在会自动创建) use mydb
查看当前数据库 db
删除当前数据库 db.dropDatabase()

2. 集合(表)相关

功能 命令
显示所有集合 show collections
创建集合 db.createCollection("users")
删除集合 db.users.drop()

3. 数据(文档)操作

插入

1
2
3
4
5
db.users.insertOne({name: "Alice", age: 25})
db.users.insertMany([
{name: "Bob", age: 30},
{name: "Charlie", age: 28}
])

查询

1
2
3
4
5
db.users.find()                          // 查询全部
db.users.find().pretty() // 格式化输出
db.users.find({name: "Alice"}) // 条件查询
db.users.find({age: {$gt: 25}}) // 年龄大于25
db.users.find({}, {name: 1, _id: 0}) // 只返回 name 字段

更新

1
2
3
4
5
6
7
8
9
db.users.updateOne(
{name: "Alice"},
{$set: {age: 26}}
)

db.users.updateMany(
{age: {$gt: 25}},
{$set: {status: "active"}}
)

删除

1
2
db.users.deleteOne({name: "Bob"})
db.users.deleteMany({age: {$lt: 20}})

4. 索引

1
2
3
db.users.createIndex({name: 1})        // 升序索引
db.users.getIndexes() // 查看索引
db.users.dropIndex("name_1") // 删除索引

5. 用户与权限

1
2
3
4
5
6
7
8
9
10
// 在 admin 数据库创建超级用户
use admin
db.createUser({
user: "admin",
pwd: "123456",
roles: [{role: "root", db: "admin"}]
})

// 查看当前数据库用户
show users

问题

时区

配置文件里的时区项不能随意修改timeZoneInfo: /usr/share/zoneinfo

如果是docker部署需要在run的时候使用 -e TZ=Asia/Shanghai,如果是宿主机则会(还不清楚)…

不管是docker还是宿主机,这项配置改动了都可能起不来。

Docker 容器中推荐用 -e TZ 方式设置时区,而不是修改 mongod.conf

配置文件修改 timeZoneInfo 只在特殊场景下使用,并且容易出错。