MongoDB学习
MongoDB 是目前最流行的开源 NoSQL 数据库之一,以其灵活的文档模型、强大的可扩展性和高性能被广泛应用于各类场景。以下从核心概念、数据模型、操作方式到高级特性进行详细讲解。MongoDB 是一个文档型 NoSQL 数据库(非关系型数据库),由 MongoDB Inc. 开发,2009 年首次发布。它摒弃了关系型数据库的表结构和固定 schema,采用灵活的文档模型存储数据,更适合处理非结
目录
前言
MongoDB 是目前最流行的开源 NoSQL 数据库之一,以其灵活的文档模型、强大的可扩展性和高性能被广泛应用于各类场景。以下从核心概念、数据模型、操作方式到高级特性进行详细讲解。
一、什么是 MongoDB?
MongoDB 是一个文档型 NoSQL 数据库(非关系型数据库),由 MongoDB Inc. 开发,2009 年首次发布。它摒弃了关系型数据库的表结构和固定 schema,采用灵活的文档模型存储数据,更适合处理非结构化或半结构化数据。
核心特性:
- 文档导向:数据以 “文档” 为基本单位,类似 JSON,结构灵活。
- 无固定 Schema:同一集合(类似表)中的文档可以有不同字段,无需预先定义结构。
- 分布式友好:原生支持副本集(高可用)和分片(水平扩展),轻松应对大数据量和高并发。
- 丰富的查询能力:支持复杂查询、聚合、索引等,功能接近关系型数据库。
- 多语言支持:提供 Java、Python、Node.js 等主流语言的驱动,易于集成开发。
二、核心概念(与关系型数据库对比)
MongoDB 的术语与关系型数据库(如 MySQL)有对应关系,但本质不同,理解这些对应关系能快速入门:
关系型数据库 | MongoDB | 说明 |
---|---|---|
数据库(Database) | 数据库(Database) | 逻辑上的独立数据集合,一个 MongoDB 实例可包含多个数据库。 |
表(Table) | 集合(Collection) | 存储文档的容器,类似表,但集合内文档结构可不同。 |
行(Row) | 文档(Document) | 一条数据记录,以 BSON 格式(类似 JSON)存储。 |
列(Column) | 字段(Field) | 文档中的键值对,对应 JSON 中的 “键”。 |
主键(Primary Key) | _id 字段 |
每个文档默认包含的唯一标识,自动生成(ObjectId 类型),也可手动指定。 |
索引(Index) | 索引(Index) | 用于加速查询,支持单字段、复合、地理空间等多种类型。 |
三、数据模型:文档与 BSON
MongoDB 的核心是文档(Document),它是数据的最小单位,采用 BSON(Binary JSON)格式存储。BSON 是 JSON 的二进制扩展,支持更多数据类型(如日期、二进制数据等),且更易被机器解析。
1. 文档结构
文档是键值对的集合,类似 JSON 对象,示例:
{
"_id": ObjectId("650a8b3d1f2d7e3a4c8d9e0f"), // 自动生成的唯一标识
"name": "张三",
"age": 28,
"isStudent": false,
"hobbies": ["篮球", "音乐"], // 数组类型
"address": { // 嵌入文档(嵌套结构)
"city": "北京",
"district": "海淀区"
},
"createTime": ISODate("2023-09-21T08:30:00Z") // 日期类型
}
2. 支持的数据类型
BSON 支持比 JSON 更丰富的类型,常见包括:
- 基本类型:字符串(String)、整数(Int32/Int64)、布尔(Boolean)、null。
- 复杂类型:数组(Array)、嵌入文档(Embedded Document)。
- 特殊类型:ObjectId(文档唯一标识)、日期(Date)、二进制数据(Binary)、正则表达式(Regex)等。
3. 集合(Collection)
集合是文档的容器,特点:
- 无固定 schema:同一集合中的文档可以有不同字段(例如,一个文档有
age
字段,另一个可以没有)。 - 动态创建:无需预先定义,插入第一个文档时自动创建集合。
四、基本操作(CRUD)
MongoDB 提供丰富的操作接口,以下是核心的增删改查(CRUD)操作示例(基于 MongoDB Shell,类似命令行工具)。
1. 创建(Create)
使用 insertOne()
插入单条文档,insertMany()
插入多条文档:
// 插入单条
db.users.insertOne({
name: "李四",
age: 30,
address: { city: "上海" }
});
// 插入多条
db.users.insertMany([
{ name: "王五", age: 25, hobbies: ["读书"] },
{ name: "赵六", age: 35, isStudent: true }
]);
2. 读取(Read)
使用 find()
查询文档,支持条件过滤、投影(指定返回字段)、排序、分页等。
-
// 查询所有文档(返回游标,需遍历) db.users.find(); // 条件查询:年龄大于 28 的用户 db.users.find({ age: { $gt: 28 } }); // $gt 表示“大于”
-
投影(只返回指定字段):
// 只返回 name 和 age 字段(_id 默认返回,需显式排除) db.users.find({ age: { $gt: 28 } }, { name: 1, age: 1, _id: 0 });
-
排序与分页:
// 按 age 降序排序,跳过前 1 条,返回 2 条 db.users.find() .sort({ age: -1 }) // -1 降序,1 升序 .skip(1) .limit(2);
3. 更新(Update)
使用 updateOne()
更新单条文档,updateMany()
更新多条,需配合更新操作符(如 $set
、$inc
等)。
-
示例:
// 更新 name 为“李四”的用户,年龄增加 1($inc 自增) db.users.updateOne( { name: "李四" }, // 查询条件 { $inc: { age: 1 } } // 更新操作 ); // 给所有年龄小于 30 的用户添加“学生”标签 db.users.updateMany( { age: { $lt: 30 } }, { $set: { isStudent: true } } );
常用更新操作符:
$set
:修改字段值$inc
:数值自增 / 减$push
:向数组添加元素$unset
:删除字段
4. 删除(Delete)
使用 deleteOne()
删除单条,deleteMany()
删除多条:
// 删除 name 为“赵六”的文档
db.users.deleteOne({ name: "赵六" });
// 删除所有年龄大于 40 的文档
db.users.deleteMany({ age: { $gt: 40 } });
五、索引:提升查询性能
索引是加速查询的关键,MongoDB 支持多种索引类型,核心作用是减少查询时扫描的文档数量。
1. 索引类型
-
单字段索引:对单个字段创建索引,最常用。
// 为 age 字段创建升序索引 db.users.createIndex({ age: 1 });
-
复合索引:对多个字段联合创建索引,遵循 “最左前缀原则”(查询条件包含左侧字段时才生效)。
// 对 name(升序)和 age(降序)创建复合索引 db.users.createIndex({ name: 1, age: -1 });
-
地理空间索引:用于地理位置查询(如 “附近的商店”)。
// 为 location 字段(存储经纬度)创建 2D 球面索引 db.shops.createIndex({ location: "2dsphere" });
-
文本索引:用于全文搜索(如搜索文档中包含 “MongoDB” 的内容)。
javascript
db.articles.createIndex({ content: "text" });
2. 索引操作
- 查看集合索引:
db.users.getIndexes()
- 删除索引:
db.users.dropIndex({ age: 1 })
3. 注意事项
- 索引会加快查询,但会减慢写入(插入 / 更新 / 删除),因为索引需要同步更新。
- 避免过度索引:每个索引都会占用存储空间,建议只为高频查询字段创建索引。
六、分布式特性:高可用与扩展
MongoDB 原生支持分布式部署,解决大规模数据和高可用需求。
1. 副本集(Replica Set):高可用保障
副本集是一组维护相同数据的 MongoDB 实例,用于实现高可用和数据冗余。
-
结构:1 个主节点(Primary)+ 多个从节点(Secondary)+ 1 个仲裁节点(Arbiter,可选)。
- 主节点:处理所有写操作和客户端查询。
- 从节点:复制主节点的数据,主节点故障时自动选举新主节点。
- 仲裁节点:不存储数据,仅参与选举(降低部署成本)。
-
作用:
- 数据备份:从节点复制主节点数据,避免单点故障丢失数据。
- 自动故障转移:主节点故障后,从节点自动选举新主节点,业务不中断。
2. 分片(Sharding):水平扩展
当数据量过大(如 TB 级),单台服务器无法承载时,分片可将数据拆分到多台服务器(分片节点),实现水平扩展。
-
核心概念:
- 分片键(Shard Key):用于拆分数据的字段(如用户 ID、时间),需提前规划(一旦确定不可修改)。
- 分片集群组件:
- 分片节点(Shard):存储实际数据(通常是副本集,保证高可用)。
- 路由节点(Mongos):接收客户端请求,转发到对应分片。
- 配置节点(Config Server):存储集群元数据(如分片键范围)。
-
作用:分散数据存储压力,支持海量数据和高并发访问。
七、事务支持
MongoDB 4.0 及以上版本支持多文档事务,可保证多个操作的原子性(要么全部成功,要么全部失败),弥补了早期 NoSQL 数据库在事务上的短板。
八、适用场景与不适用场景
适用场景:
- 大数据量、高写入场景:如日志存储、用户行为追踪(灵活 schema 适合频繁变更的数据)。
- 快速迭代的业务:如互联网产品(无需预先定义表结构,适应需求快速变化)。
- 需要地理空间查询:如地图应用(支持地理空间索引)。
- 高可用与扩展需求:如电商平台(副本集保证不宕机,分片支持海量订单)。
不适用场景:
- 强事务与复杂关联:如银行核心系统(虽然支持事务,但复杂多表 join 不如关系型数据库高效)。
- 固定 schema 且结构简单:如简单的配置表(关系型数据库更轻量)。
总结
MongoDB 以灵活的文档模型打破了关系型数据库的固定 schema 限制,同时通过副本集和分片实现高可用与水平扩展,再加上完善的查询能力和事务支持,成为 NoSQL 数据库中的佼佼者。
它特别适合处理非结构化数据、快速迭代的业务和大规模数据场景,但在强事务和复杂关联场景中,仍需权衡与关系型数据库的选择。
更多推荐
所有评论(0)