大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
MongoDB 概览
这一课你将能做到
- 说清楚 MongoDB 是什么、和 MySQL 这类关系型数据库的本质区别
- 在本机或 Atlas 上连上一个 MongoDB 7.x 实例,用 mongosh 建库、建集合、插入并查出一条文档
- 判断一个业务场景适不适合用 MongoDB,并能给出理由
为什么要学
本站的主存储是 MySQL,但很多数据天然不是「表格」形状:用户提交一份代码的判题结果,里面嵌套了测试用例数组、每条的 stdout/stderr、性能指标对象;课程进度里每个用户的「已完成课时集合」长度不一。硬塞进 MySQL 要么拆一堆关联表、要么存 JSON 字符串失去查询能力。
MongoDB 就是为这种「文档形状」的数据设计的:一条记录就是一个 BSON 文档,字段可以嵌套、可以是数组、不同文档字段可以不同。同时它在互联网厂面试里是「除了 MySQL 你还用过什么数据库」的标准答案之一,值得系统学一遍。
先建立图像
关系型 vs 文档型的对照:
MySQL(关系型) MongoDB(文档型)
┌──────────────┐ ┌─────────────────────────────┐
│ database │ │ database │
│ └─ table │ <──────────> │ └─ collection(集合) │
│ └─ row │ │ └─ document(文档) │
│ └─ col │ │ └─ field(字段) │
└──────────────┘ └─────────────────────────────┘
表结构固定(schema 强制) 结构灵活(schema-less,可校验)
JOIN 关联多表 内嵌文档为主,$lookup 为辅
一条「做题记录」在 MongoDB 里的样子:
{
"_id": ObjectId("66f1a2b3c4d5e6f708192a3b"),
"userId": 1024,
"lessonSlug": "mdbrm-intro",
"code": "db.submissions.find({userId: 1024})",
"status": "accepted",
"cases": [
{ "name": "case1", "passed": true, "costMs": 12 },
{ "name": "case2", "passed": true, "costMs": 9 }
],
"submittedAt": ISODate("2026-10-07T08:30:00Z")
}
注意:数组 cases、内嵌对象、日期、ObjectId 全部原生支持,不需要拆表。
跟着做
步骤 1:准备环境(二选一)
本地 Docker 起一个 MongoDB 7:
docker run -d --name mongo7 -p 27017:27017 mongo:7
或者注册 MongoDB Atlas 免费版(M0,512MB 存储,足够学习),拿到连接串。
安装 mongosh(官方 Shell,替代旧的 mongo shell):Windows 用 winget:
winget install MongoDB.Shell
步骤 2:连接并验证版本
mongosh "mongodb://localhost:27017"
连上后执行:
db.runCommand({ hello: 1 })
返回里能看到 maxWireVersion 和 isWritablePrimary: true,说明实例正常。
version() // 应输出 7.x.x
步骤 3:建库、建集合、插数据
MongoDB 的库和集合都是「用时即建」,不需要 CREATE:
use codeforge
db.submissions.insertOne({
userId: 1024,
lessonSlug: "mdbrm-intro",
status: "accepted",
cases: [
{ name: "case1", passed: true, costMs: 12 },
{ name: "case2", passed: false, costMs: 30 }
],
submittedAt: new Date()
})
步骤 4:查出来
db.submissions.find({ userId: 1024 })
db.submissions.findOne({ lessonSlug: "mdbrm-intro" })
步骤 5:看看有哪些库和集合
show dbs
show collections
db.stats()
讲清楚要点
- MongoDB 是文档数据库:存储单元是 BSON 文档(二进制 JSON 超集),不是行。文档属于集合(collection),集合属于数据库(database)。
- Schema-less 不等于没有结构:字段可以随时加减,但生产环境通常配合 JSON Schema 校验器(validator)或应用层模型约束,否则数据会烂掉。
- 设计哲学是「内嵌优先」:关系型里要 JOIN 的一对多数据,MongoDB 里通常内嵌成数组一次取回。是否内嵌的判断标准是「数据是否总是一起被读取」。
- 默认单机也够用,但为高可用而生:复制集(Replica Set)提供自动故障转移,分片(Sharding)提供水平扩展,这是 MongoDB 区别于很多单机数据库的核心能力。
- 适合场景:内容管理、日志/事件流、用户画像、实时分析、快速迭代的业务。不适合:强事务的财务核心、复杂多表关联为主的 ERP。
- 7.x 的关键能力:时间序列集合、Queryable Encryption(可查询加密)、compound wildcard 索引、更快的聚合与变更流。
你可能会懵的地方
- MongoDB 没有表,那数据之间怎么关联?
两种方式:内嵌(推荐,一次查询拿全)和引用(存对方的
_id,类似外键,用$lookup或应用层二次查询拼接)。绝大多数「一起读」的数据都该内嵌。 _id是什么?为什么不用自增 ID?_id是每个文档必须有的主键,默认是 ObjectId——12 字节,内含时间戳,集群内天然唯一,不需要中心化发号器,所以适合分布式。你也可以用业务 ID 覆盖它。- use 一个不存在的库不会报错?
不会。MongoDB 是惰性创建:库和集合在第一次写入数据时才真正落盘。
use codeforge后show dbs看不到它是正常的,插入一条数据后就出现了。 - MongoDB 支持事务吗? 支持。4.0 起支持复制集多文档事务,4.2 起支持分片事务。但单文档操作本身就是原子的,加上内嵌模型,大多数业务用不到多文档事务。
- 和 Redis 是竞争关系吗? 不是。Redis 是内存 KV/缓存,MongoDB 是持久化文档库。本站架构里两者互补:MySQL/MongoDB 存真相,Redis 做缓存和排行榜。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
把 MySQL 表结构原样搬进 MongoDB,全靠 $lookup 拼 | 失去文档模型优势,性能差 | 一起读的数据内嵌为一个文档 |
| 一个文档无限膨胀(如把所有提交记录塞进用户文档) | 超过 16MB 文档上限,写放大 | 超出边界的「多」侧拆成独立集合 |
用 mongo 命令连接 7.x | 旧 shell 已在 6.0 移除 | 使用 mongosh |
| 生产环境裸奔无认证、绑定 0.0.0.0 | 勒索软件重灾区 | 开认证、绑定内网、上 TLS |
| 把 MongoDB 当缓存用,数据只写不备份 | 重启/故障丢数据 | 用复制集 + 定期备份,缓存交给 Redis |
卡点急救
- mongosh 连接报
connect ECONNREFUSED:服务没起。Docker 场景执行docker ps看容器在不在,docker logs mongo7看日志;确认 27017 端口没被占用。 - 插入后
find查不到:八成是连错了库。执行db看当前库名,show dbs确认数据落在哪个库;use切错库是初学者最常见的事故。 - Atlas 连不上,报 IP 白名单错误:Atlas 默认拒绝所有来源 IP,到 Network Access 里添加当前公网 IP(学习期间可加 0.0.0.0/0,生产禁止)。
面试常问
- MongoDB 和 MySQL 怎么选? 看数据形状和访问模式:结构稳定、多表关联、强事务选 MySQL;文档形状、快速迭代、读写量大、需要水平扩展选 MongoDB。很多系统是混合用,比如本站:MySQL 存课程与用户关系,MongoDB 存提交记录与行为事件。
- MongoDB 为什么快? 三点:内嵌模型减少 JOIN;WiredTiger 存储引擎支持文档级并发和压缩;内存映射 + 索引让热数据基本在内存里。另外副本读可以分担压力。
- 16MB 文档限制怎么破?
重新建模:把无限增长的数组拆出去做独立集合(引用父文档
_id);确实需要存大文件用 GridFS。
自测三问
- MongoDB 的 database、collection、document 分别对应关系型数据库的什么概念?
- 为什么 ObjectId 适合分布式系统做主键?
- 「用户」和「该用户的登录日志」两种数据,你会内嵌还是拆集合?为什么?
小结一句话
MongoDB 用「文档」对世界建模:一起读的数据放在一起,结构随业务演进,单机起步、集群兜底。
延伸
- MongoDB 官方文档:Introduction
- MongoDB University 免费课程
- 下一课:BSON 与类型——搞懂文档里每个字段的真实类型,避开「字符串数字比较」这类深坑。