MongoDB是目前最主流的文档型NoSQL数据库,简单说就是"以JSON格式存数据的数据库",不用提前建表、改结构灵活,特别适配快速迭代的业务(比如电商、社交、AI场景)。下面用通俗的语言拆解它的核心概念、用法和适用场景。
一、核心定位:为啥选MongoDB?
先对比传统关系型数据库(比如MySQL),你就懂MongoDB的优势了:
| 维度 | MySQL(关系型) | MongoDB(文档型) |
|---|---|---|
| 数据格式 | 二维表(行+列),需提前建表/字段 | BSON(JSON的二进制扩展),无固定结构 |
| 扩展方式 | 垂直扩展(升级服务器)为主 | 水平扩展(加服务器)为主,天然适配分布式 |
| 事务支持 | 强事务(ACID),支持多表事务 | 单文档事务(默认),4.0+支持多文档事务 |
| 查询灵活性 | 结构化查询,需符合表结构 | 支持嵌套查询、数组查询,灵活度高 |
| 适用场景 | 数据结构固定(比如财务、订单) | 数据结构多变(比如用户画像、日志) |
核心特点总结:
- 无模式(Schema-less) :不用提前定义表结构,一条数据可以和另一条数据有完全不同的字段(比如一条用户数据有
age,另一条可以没有); - 文档存储:单条数据是一个"文档"(类似JSON),支持嵌套(比如用户文档里嵌套地址、订单列表);
- 高性能:内置索引、内存映射,读写速度快,支持分片(分布式存储);
- 易扩展:从单节点到集群无缝扩容,适配亿级数据量。
二、核心概念:把MySQL术语翻译成MongoDB
新手最容易懵的是术语差异,直接对应看:
| MySQL术语 | MongoDB术语 | 大白话解释 |
|---|---|---|
| 数据库(Database) | 数据库(Database) | 一样!比如test_db既是MySQL库也是MongoDB库 |
| 表(Table) | 集合(Collection) | 存放同类文档的"容器",相当于MySQL的表,但无结构限制 |
| 行(Row) | 文档(Document) | 单条数据,JSON格式(实际存BSON) |
| 列(Column) | 字段(Field) | 文档里的键值对,比如"name": "张三" |
| 主键(Primary Key) | _id字段 | 每个文档默认自带的唯一标识,MongoDB自动生成(也可以自定义) |
| 索引(Index) | 索引(Index) | 一样!支持单字段、复合、地理空间等索引 |
举个例子:
MySQL里用户表(user)的一行数据:
| id | name | age | address |
|---|---|---|---|
| 1 | 张三 | 20 | 北京市朝阳区 |
MongoDB里user集合的一个文档(BSON格式):
json
{
"_id": ObjectId("66ff7a7b8c9d4832e078b456"), // MongoDB自动生成的唯一ID
"name": "张三",
"age": 20,
"address": { // 嵌套文档
"province": "北京",
"city": "朝阳",
"street": "XX路"
},
"hobbies": ["篮球", "游戏"] // 数组字段
}
可以看到:支持嵌套字段(address)、数组字段(hobbies),这是MySQL很难做到的(需要多表关联)。
三、核心操作:常用CRUD(大白话+示例)
先装MongoDB(本地/云服务),连接后用mongo/mongosh命令行操作,核心操作如下:
1. 数据库/集合操作
bash
# 切换/创建数据库(不存在则自动创建)
use test_db
# 创建集合(可选,插入数据时会自动创建)
db.createCollection("user")
# 查看当前库的所有集合
show collections
# 删除集合
db.user.drop()
# 删除数据库
db.dropDatabase()
2. 插入数据(Create)
bash
# 插入单条文档
db.user.insertOne({
"name": "张三",
"age": 20,
"address": {"province": "北京", "city": "朝阳"},
"hobbies": ["篮球", "游戏"]
})
# 插入多条文档
db.user.insertMany([
{"name": "李四", "age": 25, "hobbies": ["读书"]},
{"name": "王五", "age": 30, "address": {"province": "上海"}}
])
注意:插入时如果user集合不存在,会自动创建;_id字段如果不指定,MongoDB会生成唯一的ObjectId。
3. 查询数据(Read)
这是MongoDB的核心优势,支持各种灵活查询:
bash
# 1. 查询所有文档(慎用!数据量大时会卡)
db.user.find()
# 2. 条件查询:年龄=20
db.user.find({"age": 20})
# 3. 条件查询:年龄>20(MongoDB用特殊操作符)
db.user.find({"age": {"$gt": 20}}) # $gt=大于,$lt=小于,$gte=大于等于
# 4. 嵌套文档查询:地址里的省份=北京
db.user.find({"address.province": "北京"})
# 5. 数组查询:爱好包含篮球
db.user.find({"hobbies": "篮球"})
# 6. 只返回指定字段(比如只返回name和age,_id默认返回,用0关闭)
db.user.find({"age": {"$gt": 20}}, {"name": 1, "age": 1, "_id": 0})
# 7. 排序:按年龄降序(1=升序,-1=降序)
db.user.find().sort({"age": -1})
# 8. 分页:跳过1条,取2条(对应MySQL的limit offset)
db.user.find().skip(1).limit(2)
# 9. 统计数量
db.user.countDocuments({"age": {"$gt": 20}})
4. 更新数据(Update)
bash
# 1. 更新单条文档:把张三的年龄改成21
db.user.updateOne(
{"name": "张三"}, # 查询条件
{"$set": {"age": 21}} # 更新操作($set=设置字段,不影响其他字段)
)
# 2. 更新多条文档:年龄>20的用户,添加字段"status": "active"
db.user.updateMany(
{"age": {"$gt": 20}},
{"$set": {"status": "active"}}
)
# 3. 替换整个文档(慎用!会覆盖所有字段,除了_id)
db.user.replaceOne(
{"name": "张三"},
{"name": "张三", "age": 21, "gender": "男"} # 新文档
)
5. 删除数据(Delete)
bash
# 删除单条文档
db.user.deleteOne({"name": "张三"})
# 删除多条文档
db.user.deleteMany({"age": {"$lt": 25}})
四、核心特性:MongoDB的"杀手锏"
1. 索引:提升查询速度
和MySQL一样,没有索引的查询会全表扫描,MongoDB支持多种索引:
bash
# 1. 创建单字段索引(年龄字段,升序)
db.user.createIndex({"age": 1})
# 2. 创建复合索引(name+age)
db.user.createIndex({"name": 1, "age": -1})
# 3. 创建唯一索引(name字段不能重复)
db.user.createIndex({"name": 1}, {"unique": true})
# 查看索引
db.user.getIndexes()
# 删除索引
db.user.dropIndex("age_1")
2. 聚合:数据统计分析
类似MySQL的group by,但功能更强,支持多阶段处理:
bash
# 按省份统计用户数量
db.user.aggregate([
{"$match": {"address.province": {"$exists": true}}}, # 过滤:有省份字段的文档
{"$group": {"_id": "$address.province", "count": {"$sum": 1}}} # 分组统计
])
结果会返回:
json
[{"_id": "北京", "count": 1}, {"_id": "上海", "count": 1}]
3. 分片:分布式存储(处理大数据)
当单节点存不下/处理不了数据时,MongoDB可以分片(把数据拆分到多个服务器):
- 分片键:按哪个字段拆分数据(比如按用户ID范围);
- 分片集群:包含分片节点、配置节点、路由节点(应用只连路由节点,透明访问所有分片)。
4. 事务:保证数据一致性
MongoDB 4.0+支持多文档事务,用法类似MySQL:
bash
# 开启事务
session = db.getMongo().startSession()
session.startTransaction()
# 事务内操作
db.user.updateOne({"name": "张三"}, {"$set": {"age": 22}}, {"session": session})
db.order.insertOne({"userId": "张三", "amount": 100}, {"session": session})
# 提交事务(失败则调用session.abortTransaction())
session.commitTransaction()
五、适用场景&避坑点
适用场景(选MongoDB准没错)
- 数据结构多变:比如用户画像(不同用户有不同的标签)、社交动态(朋友圈/微博);
- 大数据量+高并发:比如日志存储、物联网设备数据(MongoDB能扛高写入);
- 快速迭代的业务:创业公司/互联网产品,不用频繁改表结构;
- 地理空间数据:比如外卖配送、打车(MongoDB支持地理索引,快速查附近的商家/司机);
- AI场景:存储模型训练数据、用户行为数据(结构灵活,支持批量读写)。
避坑点(别踩这些坑)
- 不要把MongoDB当关系库用:虽然支持事务,但多表关联查询不如MySQL,复杂关联场景优先用MySQL;
- 避免大文档:单文档最大16MB,不要存大文件(比如视频),大文件用GridFS;
- 索引不要乱建:索引会提升查询速度,但降低写入速度,只给常用查询字段建索引;
- 不要依赖自动分片:分片需要提前规划分片键,选不好会导致数据倾斜(某台服务器数据过多);
- 生产环境要集群:单节点容易单点故障,至少部署副本集(主从+仲裁,自动故障转移)。
六、总结:MongoDB核心就是"灵活+高性能"
MongoDB的设计思想是"以文档为中心",放弃了关系型数据库的严格结构,换来极致的灵活性和扩展能力。
简单说:
- 如果你的数据结构固定、需要强事务(比如银行、财务),选MySQL;
- 如果你的数据结构多变、需要高写入/高扩展(比如互联网产品、AI数据),选MongoDB;
- 实际项目中常是"MySQL+MongoDB"混用:核心业务(订单、用户账号)用MySQL,非核心业务(用户画像、日志)用MongoDB。
新手入门建议:先装本地MongoDB,用mongosh命令行练CRUD,再学索引和聚合,最后了解副本集/分片集群(生产环境必备)。