一、MongoDB 是什么?
MongoDB 是一种开源文档型 NoSQL 数据库,以灵活的 JSON 格式(BSON)存储数据,无需固定表结构,适合处理半结构化和非结构化数据。与传统关系型数据库(如 MySQL)相比,它具有以下特点:
- 灵活的数据模型:文档结构可动态调整,适应业务需求变化。
- 水平扩展性:支持分片集群,轻松应对海量数据存储。
- 高性能读写:通过索引优化和内存缓存提升查询效率。
二、核心概念与术语对比
MongoDB 术语 | 对应关系型数据库术语 | 说明 |
---|---|---|
数据库(Database) | 数据库 | 存储文档集合的容器 |
集合(Collection) | 表(Table) | 一组文档的集合,类似表,但无固定模式 |
文档(Document) | 行(Row) | 数据的基本单位,类似 JSON 对象,可包含嵌套结构 |
字段(Field) | 列(Column) | 文档中的键值对,值可包含数组、对象等复杂类型 |
索引(Index) | 索引 | 用于加速查询,支持单字段、复合字段和地理空间索引 |
三、数据模型与文档结构
MongoDB 的文档以 BSON(Binary JSON)格式存储,支持嵌套数据结构。例如,一个电商商品文档:
{
"_id": ObjectId("64a1b2c3d4e5f6g7h8i9j0"),
"name": "智能手表",
"price": 1299.00,
"category": "电子产品",
"specs": {
"screen": "1.39英寸AMOLED",
"battery": "420mAh"
},
"tags": ["智能设备", "可穿戴", "运动"],
"reviews": [
{ "user": "张三", "rating": 4, "comment": "续航不错" },
{ "user": "李四", "rating": 5, "comment": "功能齐全" }
]
}
优势: 嵌套结构减少关联查询,提升复杂数据的读写效率。
四、CRUD 操作基础语法
1. 创建(Create)
// 插入单个文档
db.products.insertOne({ name: "笔记本电脑", price: 5999 });
// 插入多个文档
db.products.insertMany([
{ name: "手机", price: 3999, tags: ["5G"] },
{ name: "平板", price: 2499, tags: ["触控"] }
]);
3. 查询(Read)
// 查询所有文档
db.products.find();
// 条件查询(价格大于4000)
db.products.find({ price: { $gt: 4000 } });
// 多条件查询(价格大于4000且包含5G标签)
db.products.find({ price: { $gt: 4000 }, tags: "5G" });
// 投影(只返回指定字段)
db.products.find({}, { name: 1, price: 1, _id: 0 });
4. 更新(Update)
// 更新单个文档(设置价格为6299)
db.products.updateOne(
{ name: "笔记本电脑" },
{ $set: { price: 6299 } }
);
// 批量更新(所有5G产品价格增加100)
db.products.updateMany(
{ tags: "5G" },
{ $inc: { price: 100 } }
);
5. 删除(Delete)
// 删除单个文档
db.products.deleteOne({ name: "平板" });
// 删除所有价格低于3000的文档
db.products.deleteMany({ price: { $lt: 3000 } });
6.高级查询操作符
比较操作符
- $eq:等于
- $ne:不等于
- $gt:大于
- $gte:大于等于
- $lt:小于
- $lte:小于等于
- $in:包含在数组中
- $nin:不包含在数组中
示例:
// 查询年龄在20到30之间的用户
db.users.find({ age: { $gte: 20, $lte: 30 } });
// 查询爱好包含"reading"的用户
db.users.find({ hobbies: { $in: ["reading"] } });
逻辑操作符
- $and:逻辑与
- $or:逻辑或
- $not:逻辑非
- $nor:既不… 也不…
示例:
// 查询年龄小于25或大于35的用户
db.users.find({ $or: [{ age: { $lt: 25 } }, { age: { $gt: 35 } }] });
元素操作符
- $exists:判断字段是否存在
- $type:判断字段类型
示例:
// 查询包含email字段的用户
db.users.find({ email: { $exists: true } });
数组操作符
- $all:匹配数组中所有元素
- $elemMatch:匹配数组中至少一个元素
- $size:匹配数组长度
示例:
// 查询hobbies数组长度为2的用户
db.users.find({ hobbies: { $size: 2 } });
五、索引与性能优化
索引是提升查询效率的关键。例如,为 tags 字段创建索引:
// 创建单字段索引
db.products.createIndex({ tags: 1 });
// 创建复合索引(价格降序+名称升序)
db.products.createIndex({ price: -1, name: 1 });
// 创建唯一索引
db.users.createIndex({ email: 1 }, { unique: true });
// 查看索引
db.users.getIndexes();
// 删除索引(index_name可通过getIndexes()获取)
db.users.dropIndex("index_name");
// 查看索引使用情况
db.products.aggregate([{ $indexStats: {} }]);
六、存储引擎:WiredTiger vs. RocksDB
核心架构与性能模型对比
维度 | RocksDB | WiredTiger |
---|---|---|
存储结构 | LSM 树(Log-Structured Merge Tree) | B 树家族(B + 树变种) |
写入性能 | 极高(顺序写入优势) | 中等(随机写入需维护 B 树索引) |
读取性能 | 中等(存在读放大问题) | 极高(B 树直接定位数据) |
内存占用 | 低(仅需少量内存维护 memtable) | 高(需缓存 B 树节点和数据页) |
磁盘 IO 模式 | 顺序写入为主 | 随机读写混合 |
压缩支持 | 内置多种压缩算法(Zstandard/Snappy) | 支持压缩但需额外配置 |
典型场景 TPS 对比 | 写入密集型:10 万 + | 读写均衡型:5 万 - 8 万 |
1.WiredTiger(默认引擎):
- 优势:读写均衡,支持文档级锁,适合复杂查询和事务场景(如电商订单、社交数据)。
- 场景:读写混合、需要高查询性能的业务。
2.RocksDB:
- 优势:高写入吞吐量,存储压缩率高,适合日志记录、时序数据。
- 场景:海量数据写入、成本敏感的归档存储。
七、适用场景与典型案例
1.互联网应用:
- 电商平台(商品详情、订单数据)、社交平台(用户动态、关系链)。
- 原因:灵活的数据模型适配频繁的业务迭代。
2.物联网与日志系统:
- 设备监控数据、用户行为日志。
- 原因:支持海量非结构化数据存储,RocksDB 引擎优化写入性能。
3.实时分析与仪表盘:
- 运营数据统计、用户画像分析。
- 原因:聚合操作高效,支持实时数据查询。
八、常用工具推荐
1.图形化工具:
- MongoDB Compass:官方工具,适合新手可视化操作。
- Robo 3T:轻量级跨平台工具,支持脚本执行。
2.命令行工具:
- mongosh:新一代 Shell,支持 JavaScript 语法和智能提示。
3.监控与运维:
- MongoDB Atlas:官方云服务,提供自动化监控和备份。
- Prometheus + Grafana:开源组合,自定义监控仪表盘。
九、MongoDB 与 SQL 差异
1.核心差异
功能 | MongoDB | SQL 数据库(如 MySQL) |
---|---|---|
数据模型 | 文档(JSON/BSON) | 表结构(固定模式) |
关联查询 | $lookup 聚合操作(类似 JOIN) | JOIN 语句 |
事务支持 | 支持多文档事务(4.0+) | 支持行级事务 |
水平扩展 | 原生分片集群(Sharding) | 需要中间件(如 MyCat) |
2.语法差异
|
十、总结:为什么选择 MongoDB?
MongoDB 以其灵活的数据模型、强大的扩展性和生态工具链,成为处理非结构化数据的首选方案。无论是互联网初创公司还是企业级应用,它都能在快速迭代和高性能之间找到平衡。如果你需要存储动态变化的数据、应对海量数据查询,或构建实时分析系统,MongoDB 会是一个值得考虑的选择。