MongoDB 全方位指南:部署、运维、开发与核心功能#
MongoDB 是一个基于分布式文件存储(BSON)的文档型数据库(NoSQL),旨在为 Web 应用提供可扩展的高性能数据存储解决方案。它以灵活的模式(Schema-less)、高可用性和水平扩展能力著称。
1. 部署与安装#
1.1 Linux (以 Ubuntu/Debian 为例)#
官方推荐使用 MongoDB 官方仓库安装,而非系统自带的旧版本。
# 1. 导入公钥
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | sudo gpg --dearmor -o /usr/share/keyrings/mongodb-server-7.0.gpg
# 2. 添加源 (以 Ubuntu 22.04 jammy 为例)
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
# 3. 更新并安装
sudo apt-get update
sudo apt-get install -y mongodb-org
# 4. 启动服务
sudo systemctl start mongod
sudo systemctl enable mongod
# 5. 检查状态
sudo systemctl status mongod1.2 Docker 部署 (推荐用于开发/测试)#
docker run --name some-mongo \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=secret \
-p 27017:27017 \
-v mongodata:/data/db \
-d mongo:7.0注意:生产环境建议配置副本集(Replica Set)以支持事务和自动故障转移。
1.3 初始配置关键点 (/etc/mongod.conf)#
- 绑定 IP: 默认只监听
127.0.0.1。若要远程访问,需修改为bindIp: 0.0.0.0(配合防火墙使用) 或指定内网 IP。 - 安全认证: 设置
security.authorization: enabled以开启用户名密码验证。 - 存储引擎: 默认且推荐使用
WiredTiger。
# 示例配置片段
net:
port: 27017
bindIp: 0.0.0.0
security:
authorization: enabled
storage:
dbPath: /var/lib/mongodb
wiredTiger:
engineConfig:
cacheSizeGB: 2.5 # 建议设为物理内存的 50%-60%2. 日常使用命令 (增删改查)#
MongoDB 使用 JavaScript 风格的 Shell (mongosh) 进行操作。数据以 BSON (Binary JSON) 格式存储。
2.1 连接数据库#
# 本地连接
mongosh
# 远程连接 (指定用户、数据库)
mongosh "mongodb://admin:secret@192.168.1.50:27017/mydb?authSource=admin"2.2 基础 CRUD 操作#
假设我们操作集合 users。
创建 (Insert)#
// 插入单条文档
db.users.insertOne({
username: "alice",
email: "alice@example.com",
age: 25,
tags: ["dev", "golang"],
createdAt: new Date()
});
// 插入多条文档
db.users.insertMany([
{ username: "bob", age: 30 },
{ username: "charlie", age: 28 }
]);查询 (Find)#
// 查询所有
db.users.find();
// 条件查询 (等于)
db.users.find({ age: 25 });
// 复杂条件 (大于、in、正则)
db.users.find({
age: { $gt: 20, $lt: 40 }, // 20 < age < 40
username: { $regex: /^a/i }, // 以 a 开头,不区分大小写
tags: "dev" // 数组中包含 "dev"
});
// 投影 (只返回特定字段)
db.users.find({ age: 25 }, { username: 1, email: 1, _id: 0 });
// 排序与限制
db.users.find().sort({ age: -1 }).limit(5); // 按年龄降序取前 5
更新 (Update)#
注意:更新操作符必须以 $ 开头,否则会用新文档替换整个旧文档。
// 更新单个字段 ($set)
db.users.updateOne(
{ username: "alice" },
{ $set: { email: "new_alice@example.com" } }
);
// 增加数值 ($inc)
db.users.updateOne(
{ username: "bob" },
{ $inc: { age: 1 } }
);
// 数组操作 ($push, $pull)
db.users.updateOne(
{ username: "alice" },
{ $push: { tags: "python" } } // 添加标签
);
// 更新多条 (updateMany)
db.users.updateMany(
{ age: { $lt: 18 } },
{ $set: { status: "minor" } }
);删除 (Delete)#
// 删除匹配的第一条
db.users.deleteOne({ username: "charlie" });
// 删除所有匹配项
db.users.deleteMany({ age: { $gt: 100 } });
// 清空集合 (类似 TRUNCATE)
db.users.drop(); // 删除整个集合(包括索引)
// 或者
db.users.deleteMany({}); // 仅删除数据,保留索引
3. 运维与研发常用命令#
3.1 运维人员 (DBA) 常用命令#
| 场景 | 命令/Shell 操作 | 说明 |
|---|---|---|
| 查看数据库列表 | show dbs | 列出所有库 |
| 查看集合列表 | show collections | 列出当前库下的表 |
| 查看索引 | db.collection.getIndexes() | 查看集合的索引定义 |
| 查看当前操作 | db.currentOp() | 监控正在运行的查询/写入 (类似 pg_stat_activity) |
| 杀掉进程 | db.killOp(opid) | 终止卡死的操作 (opid 来自 currentOp) |
| 数据库统计 | db.stats() | 查看库的大小、对象数量 |
| 集合统计 | db.collection.stats() | 查看集合大小、索引大小、文档数 |
| 修复集合 | db.runCommand({ repairCollection: "name" }) | 修复损坏的集合 (需停机或特定模式) |
| 备份 (逻辑) | mongodump --uri="..." --out=/backup | 导出 BSON 文件 |
| 恢复 (逻辑) | mongorestore --uri="..." /backup | 从 BSON 文件恢复 |
| 查看副本集状态 | rs.status() | 核心,查看主从节点健康状态 |
| 日志分析 | tail -f /var/log/mongodb/mongod.log | 实时监控错误和慢查询 |
3.2 研发人员 (Dev) 常用命令#
| 场景 | 命令/Shell 操作 | 说明 |
|---|---|---|
| 执行计划分析 | db.collection.find({...}).explain("executionStats") | 核心,查看是否走索引、扫描行数、耗时 |
| 聚合管道 | db.collection.aggregate([...]) | 处理复杂数据统计、转换 (类似 SQL Group By/Join) |
| 随机采样 | db.collection.aggregate([ { $sample: { size: 10 } } ]) | 随机抽取文档用于测试 |
| distinct 去重 | db.collection.distinct("username") | 获取某字段的所有唯一值 |
| TTL 索引 | db.collection.createIndex({ "createdAt": 1 }, { expireAfterSeconds: 3600 }) | 自动删除 1 小时前的数据 (日志/会话常用) |
| 文本搜索 | db.collection.createIndex({ content: "text" })db.collection.find({ $text: { $search: "mongodb" } }) | 全文检索功能 |
| 查看慢查询 | db.setProfilerLevel(1, { slowms: 100 }) | 开启性能分析器,记录超过 100ms 的操作 |
4. 核心自带功能讲解#
4.1 灵活的 Schema (BSON)#
无需预定义表结构,文档字段可以随时增减。支持嵌套文档和数组,非常适合存储层级数据(如评论回复、商品属性)。
// 一个文档可以直接包含复杂的嵌套结构
{
_id: ObjectId("..."),
order_id: "ORD123",
customer: { name: "Alice", address: { city: "Beijing", zip: "100000" } },
items: [
{ product: "Laptop", qty: 1, price: 8000 },
{ product: "Mouse", qty: 2, price: 100 }
]
}4.2 聚合框架 (Aggregation Framework)#
MongoDB 最强大的数据处理工具,通过管道(Pipeline)阶段处理数据。
db.orders.aggregate([
{ $match: { status: "shipped" } }, // 1. 过滤
{ $unwind: "$items" }, // 2. 展开数组
{ $group: {
_id: "$items.product", // 3. 按商品分组
totalQty: { $sum: "$items.qty" }, // 计算总销量
avgPrice: { $avg: "$items.price" }
}},
{ $sort: { totalQty: -1 } }, // 4. 排序
{ $limit: 10 } // 5. 取前 10
]);4.3 副本集 (Replica Set) - 高可用#
MongoDB 的高可用方案。由一个 Primary (主节点,负责写) 和多个 Secondary (从节点,负责读/备份) 组成。
- 自动故障转移: 主节点挂掉后,从节点自动选举出新主。
- 数据冗余: 数据在多份节点上保存。
- 读扩展: 可以配置应用读取从节点数据(Read Preference)。
4.4 分片 (Sharding) - 水平扩展#
当数据量超过单机承载能力时,通过分片将数据分布到多台机器上。
- Shard Key: 选择分片键至关重要(如
user_id或time),选错会导致数据倾斜(Jumbo Chunks)。 - Config Server: 存储集群元数据。
- Mongos: 路由进程,应用连接 Mongos,由它转发请求到具体分片。
4.5 索引类型#
除了默认的 _id 索引,还支持:
- 单键/复合索引: 加速常规查询。
- 多键索引 (Multikey): 自动为数组字段创建索引。
- 地理空间索引 (2dsphere): 支持 GeoJSON 查询(附近的人、范围内搜索)。
- 文本索引 (Text): 支持多语言分词搜索。
- 哈希索引: 常用于分片键,使数据分布更均匀。
4.6 事务 (ACID Transactions)#
从 4.0 版本开始支持多文档事务(需在副本集或分片集群环境下)。
const session = db.getMongo().startSession();
session.startTransaction();
try {
db.accounts.updateOne({ _id: 1 }, { $inc: { balance: -100 } }, { session });
db.accounts.updateOne({ _id: 2 }, { $inc: { balance: 100 } }, { session });
session.commitTransaction();
} catch (error) {
session.abortTransaction();
throw error;
} finally {
session.endSession();
}5. 注意事项与最佳实践#
5.1 性能与建模#
- /embed vs /reference:
- 嵌入 (Embed): 适合“一对一”或“一对少”且经常一起读取的数据(如订单和订单项)。读取性能极高(一次 IO)。
- 引用 (Reference): 适合“一对多”且子文档独立增长、或数据量巨大的情况(如用户和评论)。避免文档超过 16MB 限制。
- 索引覆盖: 尽量让查询字段和返回字段都在索引中,避免回表扫描文档。
- 避免全表扫描: 生产环境严禁在没有索引的大集合上进行
$regex(带头部通配符除外) 或无条件查询。
5.2 运维安全#
- 开启认证: 默认安装通常无密码,生产环境必须开启
authorization并创建具有最小权限的用户。 - 网络隔离: 不要将 MongoDB 端口 (27017) 直接暴露在公网。使用防火墙限制访问 IP,或通过 SSH 隧道/VPC 内网访问。
- 备份策略:
- 小数据量:
mongodump定期执行。 - 大数据量/高可用:使用 文件系统快照 (LVM/EBS Snapshot) 配合 Oplog 回放,或使用 MongoDB Cloud Manager / Ops Manager。
- 小数据量:
5.3 常见陷阱#
- 文档增长导致移动: 如果频繁更新文档导致其大小增加,MongoDB 可能需要移动文档位置,产生碎片并降低性能。设计上尽量预估字段大小,或使用
$setOnInsert预留空间。 - 内存压力: WiredTiger 依赖操作系统的文件系统缓存。确保服务器有足够的空闲内存(RAM > 数据集大小最佳,至少 > 热数据大小)。
- $lookup 性能: 虽然支持类似 SQL Join 的
$lookup,但在大数据量下性能开销较大。尽量在数据模型设计阶段通过“嵌入”或“应用层 Join”来规避。 - 分片键选择: 一旦选定分片键,后续极难修改。错误的分片键(如单调递增的时间戳)会导致所有写入集中在最后一个分片(热点写入),失去分片意义。
5.4 监控建议#
监控核心指标:
- Connections: 当前连接数是否接近上限。
- Queue Length: 读写队列长度,若长期大于 0 说明性能瓶颈。
- Page Faults: 页面错误次数,过高说明内存不足,频繁发生磁盘 IO。
- Replication Lag: 主从延迟时间,过高会影响读一致性和故障转移。
- Asserts: 警告和错误计数。
MongoDB 以其灵活性和扩展性成为现代应用架构(尤其是微服务和 IoT 场景)的首选数据库之一。掌握其独特的文档建模思维和聚合管道,是发挥其最大价值的关键。