可以将 MongoDB 理解成一个 “灵活的文件柜”—— 它是一款非关系型数据库(NoSQL),不像 MySQL 那样用 “表格 + 行 + 列” 的固定结构存数据,而是用 “文档”(类似 JSON)的形式存数据,想存什么字段就存什么,特别适合存储非结构化、半结构化数据。
一、核心概念:用 “文件柜” 类比
MongoDB 里的专业术语,对应到 “文件柜整理文件” 的场景,全是熟悉的逻辑:
|
MongoDB 概念 |
生活类比(文件柜场景) |
对应 MySQL 概念 |
通俗解释 |
|
数据库(Database) |
整个文件柜(列如 “公司文件柜”) |
数据库(Database) |
存储一组相关数据的 “容器”,列如 “电商数据库”“社交 APP 数据库” |
|
集合(Collection) |
文件柜里的抽屉(列如 “员工档案抽屉”) |
表(Table) |
把同类文档归为一组,列如 “用户集合”“商品集合”,不用提前定义结构(列如 “员工抽屉” 里的文件,有的有 “学历” 页,有的没有,都能放) |
|
文档(Document) |
抽屉里的单份文件(列如 “张三的员工档案”) |
行(Row) |
MongoDB 最小的数据单元,用 BSON(二进制 JSON)格式存储,列如一条用户数据:{name: “张三”, age: 25, address: {city: “北京”, street: “XX路”}} |
|
字段(Field) |
文件里的具体条目(列如 “姓名:张三”) |
列(Column) |
文档里的 “细分信息”,列如上面的name“age”“address”,字段可以灵活增减(列如给张三的文档加个hobby: [“跑步”, “看书”],不用改其他文档) |
|
BSON |
带 “特殊附件” 的文件格式 |
– |
比 JSON 功能强:支持日期、二进制、数组等类型(列如 JSON 存不了 “日期”,BSON 可以) |
二、MongoDB 的核心特点:“灵活”
1. 文档模型灵活,不用固定 “表结构”
列如电商的 “商品”:
- 手机商品需要 “品牌、内存、像素” 字段;
- 衣服商品需要 “尺码、颜色、材质” 字段;
- 在 MySQL 里,得建两张表(或用复杂的关联表),但在 MongoDB 里,直接存在同一个 “商品集合” 里,各自的文档有各自的字段,互不影响。
2. 天生支持海量数据和高并发
MongoDB 支持 “分片集群”(把数据分散到多台服务器),能轻松存上亿条数据,还能通过多台服务器分担读写压力,应对高并发(列如电商大促时的商品查询、用户下单)。
3. 支持复杂查询和索引
别看结构灵活,查询能力确很强:
- 能按字段筛选(列如 “查年龄> 20 的用户”);
- 能查嵌套字段(列如 “查地址在‘北京’的用户”);
- 能给字段建索引(列如给name“商品 ID” 建索引,查询速度翻倍);
- 还支持聚合查询(列如 “统计每个城市的用户数量”)。
4. 容易扩展
- 水平扩展:想存更多数据?直接加服务器(分片),不用改代码;
- 字段扩展:给文档加新字段,直接存就行,不用像 MySQL 那样 “ALTER TABLE” 改表结构(改表结构可能锁表,影响性能)。
三、优缺点:什么时候选 MongoDB?
|
优点 |
缺点 |
|
1. 结构灵活,适合非结构化 / 半结构化数据(列如日志、社交动态、商品属性); |
1. 不支持事务的 “强一致性”(早期版本不支持事务,目前支持,但不如 MySQL 成熟,适合 “最终一致” 场景); |
|
2. 海量数据存储 + 高并发读写能力强; |
2. 不适合复杂的 “多表关联查询”(列如 “查用户 + 订单 + 物流” 的关联,MySQL 更高效); |
|
3. 扩展简单,水平扩容成本低; |
3. 占用空间比 MySQL 大(BSON 格式比表格存储冗余); |
|
4. 查询语法直观(类似 JSON),容易上手。 |
4. 对 “数据一致性” 要求极高的场景(列如金融交易),不如 MySQL 靠谱。 |
四、典型应用场景
1. 电商商品 / 订单数据
- 商品属性多样(不同品类字段不同)、订单数据包含嵌套信息(列如订单详情、收货地址、商品列表),用文档模型刚好适配;
- 大促时高并发读写,分片集群能扛住压力。
2. 日志 / 监控数据
- 服务器日志、APP 埋点数据(列如用户点击行为),字段不固定(有的日志有 “错误码”,有的没有),MongoDB 不用固定结构,直接批量写入。
3. 社交 APP 数据
- 用户动态、评论、关注关系:列如一条动态可能有文字、图片、视频链接、评论列表,用嵌套文档存,查询时一次就能取到所有相关数据(不用像 MySQL 那样多表关联)。
4. IoT 设备数据
- 传感器采集的实时数据(列如温度、湿度、设备状态),数据量大、字段可能随设备升级增减,MongoDB 能灵活存储,还支持按时间范围快速查询。
5. 内容管理系统(CMS)
- 文章、视频、音频等内容,有的有 “标签”,有的有 “作者简介”,有的有 “点赞数”,结构灵活,适合用文档存储。
五、MongoDB vs MySQL:怎么选?
|
对比维度 |
MongoDB |
MySQL |
|
数据结构 |
文档(BSON),灵活无固定结构 |
表格(行 + 列),固定结构 |
|
核心优势 |
灵活、海量数据、高并发、易扩展 |
强一致性、事务成熟、复杂关联查询高效 |
|
适用场景 |
非结构化 / 半结构化数据、高并发海量数据(电商商品、日志、社交) |
结构化数据、强一致性要求高(金融交易、用户账户、订单支付) |
选型提议:
- 如果需要 “固定结构、数据不能错、要复杂关联查询”(列如银行转账、用户余额),选 MySQL;
- 如果需要 “灵活结构、存海量数据、高并发读写”(列如电商商品、APP 日志),选 MongoDB;
- 实际项目中,两者常 “配合使用”:列如电商系统,用 MySQL 存订单支付数据(强一致性),用 MongoDB 存商品和用户动态数据(灵活 + 高并发)。
六、总结
MongoDB 是一款 “灵活、能扛量” 的非关系型数据库,核心优势是文档模型无固定结构、支持海量数据和高并发,适合存储非结构化 / 半结构化数据;如果数据结构固定、一致性要求极高,还是得选 MySQL。
七、MongoDB 常用操作命令
命令基于 MongoDB Shell(类似 MySQL 命令行),用「用户集合(user)」「商品集合(product)」举例,语法直观(类似 JSON),上手即用:
1. 数据库操作
|
命令 |
语法 |
示例 |
说明 |
|
查看所有数据库 |
show dbs |
show dbs |
显示所有已创建的数据库(空数据库不显示) |
|
切换 / 创建数据库 |
use 数据库名 |
use ecommerce(切换到电商数据库,不存在则创建) |
切换后需插入数据,数据库才会实际存在 |
|
查看当前数据库 |
db |
db |
返回当前所在数据库名称 |
|
删除当前数据库 |
db.dropDatabase() |
db.dropDatabase() |
谨慎使用!删除当前选中的数据库 |
2. 集合操作(对应 “文件柜抽屉操作”)
|
命令 |
语法 |
示例 |
说明 |
|
查看所有集合 |
show collections |
show collections |
显示当前数据库下的所有集合 |
|
创建集合 |
db.createCollection(“集合名”) |
db.createCollection(“user”) |
手动创建集合(也可直接插入文档自动创建) |
|
删除集合 |
db.集合名.drop() |
db.user.drop() |
删除指定集合及所有数据 |
3. 文档操作(核心!增删改查,对应 “文件操作”)
(1)新增文档(存文件)
- 单个新增:db.集合名.insertOne(文档)示例:db.user.insertOne({name: “张三”, age: 25, address: {city: “北京”}, hobby: [“跑步”, “看书”]})说明:文档自动生成唯一_id(类似主键),字段灵活,可嵌套(address)、可存数组(hobby)。
- 批量新增:db.集合名.insertMany([文档1, 文档2…])示例:db.user.insertMany([{name: “李四”, age: 28}, {name: “王五”, gender: “男”}])说明:允许文档字段不一致(李四没有 gender,王五没有 address,都能存)。
(2)查询文档(找文件)
- 查询所有:db.集合名.find()示例:db.user.find() → 返回所有用户文档(默认显示 20 条,按_id排序)。
- 条件查询:db.集合名.find(查询条件)示例 1(等值查询):db.user.find({name: “张三”}) → 查姓名为张三的用户。示例 2(范围查询):db.user.find({age: {$gt: 25}}) → 查年龄 > 25 的用户($gt= 大于,$lt= 小于,$eq= 等于)。示例 3(嵌套字段查询):db.user.find({“address.city”: “北京”}) → 查地址在北京市的用户(嵌套字段用引号 + 点分隔)。
- 限制返回条数:db.集合名.find().limit(数量)示例:db.user.find().limit(5) → 返回前 5 条用户。
- 排序:db.集合名.find().sort({字段: 1/-1})(1 = 升序,-1 = 降序)示例:db.user.find().sort({age: -1}) → 按年龄降序排列。
(3)修改文档(改文件)
- 修改单个文档:db.集合名.updateOne(查询条件, {修改操作})示例:db.user.updateOne({name: “张三”}, {$set: {age: 26, hobby: [“跑步”, “旅行”]}})说明:$set表明 “更新指定字段”,不影响其他字段(列如张三原本的 address 字段保留);如果不加$set,会用新文档覆盖原文档。
- 批量修改:db.集合名.updateMany(查询条件, {修改操作})示例:db.user.updateMany({age: {$lt: 25}}, {$set: {level: “年轻用户”}}) → 给所有年龄 < 25 的用户加 level 字段。
(4)删除文档(删文件)
- 删除单个文档:db.集合名.deleteOne(查询条件)示例:db.user.deleteOne({name: “王五”}) → 删除姓名为王五的第一个匹配文档。
- 批量删除:db.集合名.deleteMany(查询条件)示例:db.user.deleteMany({age: {$gt: 30}}) → 删除所有年龄 > 30 的用户。
4. 索引操作(提速查询,对应 “给文件贴标签”)
- 创建索引:db.集合名.createIndex({字段: 1/-1})(1 = 升序索引,-1 = 降序索引)示例:db.user.createIndex({name: 1}) → 给 name 字段建升序索引,查询 name 时速度翻倍。
- 查看索引:db.集合名.getIndexes()示例:db.user.getIndexes() → 显示 user 集合的所有索引(默认_id字段有主键索引)。
- 删除索引:db.集合名.dropIndex({字段: 1/-1})示例:db.user.dropIndex({name: 1}) → 删除 name 字段的索引。
八、MongoDB 分片集群原理(类比:“文件柜分多个抽屉 + 管理员”)
当数据量达到千万 / 亿级,单台服务器存不下或扛不住高并发时,就需要 “分片集群”—— 把数据分散到多台服务器,共同承担存储和查询压力。
1. 核心组件(3 个角色缺一不可)
- 分片(Shard):实际存储数据的 “服务器节点”(类似多个小文件柜)。每个分片存储数据的一部分,列如分片 1 存北京用户,分片 2 存上海用户。
- 配置服务器(Config Server):“集群管理员”,存储集群的元数据(列如 “哪些数据存在哪个分片”“索引信息”)。查询时,先问配置服务器 “数据在哪个分片”,再直接去对应分片查,不用遍历所有分片。
- 路由服务器(Mongos):“用户接口”,客户端(列如 APP、后端程序)只和路由服务器通信,不用关心分片在哪。路由服务器接收查询请求,通过配置服务器找到目标分片,返回结果(对客户端透明,像操作单台 MongoDB 一样)。
2. 数据分片规则(怎么把数据分到不同分片?)
核心是 “分片键(Shard Key)”—— 选择一个字段作为分片依据,列如用户集合选address.city(城市)、商品集合选price(价格)。
常见分片策略:
- 范围分片:按分片键的范围分配数据。列如按价格分片,0-100 元的商品存在分片 1,101-500 元存在分片 2,501 元以上存在分片 3。适合范围查询(列如查 100-300 元的商品,只查分片 1 和 2)。
- 哈希分片:对分片键做哈希计算,把数据均匀分散到所有分片。列如用户 ID 哈希后,随机分配到分片 1、2、3。适合随机查询(列如按用户 ID 查,数据均匀分布,所有分片分担压力)。
3. 分片集群的优势
- 水平扩展:想存更多数据、扛更高并发,直接加分片服务器(不用改代码);
- 高可用:每个分片可以配置副本(类似 Redis 主从),分片宕机后,副本自动接管,数据不丢失;
- 负载均衡:配置服务器自动监控各分片的负载,把新数据分配到负载低的分片。


