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 mongod

1.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_idtime),选错会导致数据倾斜(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 场景)的首选数据库之一。掌握其独特的文档建模思维和聚合管道,是发挥其最大价值的关键。