MongoDB 概念解析
MongoDB 使用一系列独特的概念和术语。本章将详细解析 MongoDB 的核心概念,帮助你建立扎实的理论基础。
核心概念对比
MongoDB vs 关系型数据库
| 关系型数据库 | MongoDB | 说明 |
|---|---|---|
| 数据库 | 数据库 | 物理容器,包含多个集合 |
| 表 | 集合 | 文档的容器,无固定模式 |
| 行 | 文档 | 基本数据单位,BSON 格式 |
| 列 | 字段 | 文档中的键值对 |
| 主键 | _id | 自动生成的唯一标识符 |
| 索引 | 索引 | 提高查询性能的数据结构 |
| 表连接 | 嵌入文档 | 通过嵌套或引用来关联数据 |
数据库(Database)
定义
数据库是集合的物理容器,每个数据库在文件系统中有独立的文件集。
特点
- 一个 MongoDB 实例可包含多个数据库
- 数据库之间相互独立,有不同的权限控制
- 命名规范:小写字母,最多 64 字节
javascript
// 查看所有数据库
show dbs
// 切换/创建数据库
use mydb
// 查看当前数据库
db
// 删除当前数据库
db.dropDatabase()保留数据库名称
- admin: 权限管理数据库
- local: 存储本地服务器数据,不复制
- config: 分片集群配置信息
集合(Collection)
定义
集合是 MongoDB 文档的组,类似于关系型数据库中的表,但不需要预定义模式。
特点
- 集合中的文档可以有不同的字段
- 动态模式,灵活适应数据变化
- 命名不能以 "system." 开头(系统保留)
javascript
// 创建集合
db.createCollection("users")
// 查看集合列表
show collections
// 删除集合
db.users.drop()
// 查看集合统计信息
db.users.stats()集合类型
- 普通集合:标准文档集合
- 固定集合(Capped Collection):固定大小的集合,支持循环覆盖
文档(Document)
定义
文档是 MongoDB 中的基本数据单元,采用 BSON(Binary JSON)格式存储。
BSON 特点
- 支持更多数据类型(Date、ObjectId、Binary 等)
- 二进制编码,解析效率更高
- 支持嵌套文档和数组
文档结构
javascript
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"name": "张三",
"age": 25,
"email": "zhangsan@example.com",
"isActive": true,
"createdAt": ISODate("2024-01-15T08:30:00Z"),
"address": {
"street": "长安街1号",
"city": "北京",
"zipCode": "100000"
},
"hobbies": ["读书", "游泳", "编程"],
"metadata": {
"loginCount": 15,
"lastLogin": ISODate("2024-01-20T10:00:00Z")
}
}文档限制
- 最大文档大小:16MB
- 最大嵌套层级:100 层
- 字段名不能包含
$和.字符
字段(Field)
定义
字段是文档中的键值对,相当于关系型数据库中的列。
命名规则
- 字段名是字符串
- 不能包含
$字符(保留用于操作符) - 不能以
.开头或结尾 - 不能包含空字符(null)
_id是保留字段,作为主键
数据类型
| 类型 | 示例 | 说明 |
|---|---|---|
| String | "hello" | UTF-8 字符串 |
| Integer | 42 | 整数值 |
| Double | 3.14 | 浮点数 |
| Boolean | true | 布尔值 |
| Date | ISODate(...) | 日期时间 |
| Null | null | 空值 |
| Array | [1, 2, 3] | 数组 |
| Object | {a: 1} | 嵌套文档 |
| ObjectId | ObjectId(...) | 12 字节唯一 ID |
| Binary Data | BinData(...) | 二进制数据 |
| Timestamp | Timestamp(...) | 时间戳 |
_id 字段
定义
每个文档都必须有 _id 字段,作为主键唯一标识文档。
特点
- 自动创建唯一索引
- 如果不指定,MongoDB 自动生成 ObjectId
- 可以自定义,但必须唯一
ObjectId 结构
507f1f77bcf86cd799439011
\____/\____/\________/\____/
时间 机器 进程ID 随机数
4字节 3字节 2字节 3字节javascript
// 获取 ObjectId 的时间戳
ObjectId("507f1f77bcf86cd799439011").getTimestamp()
// 输出: ISODate("2012-10-17T20:46:47Z")索引(Index)
定义
索引是特殊的数据结构,存储集合中部分数据的有序子集,用于提高查询效率。
索引类型
- 单字段索引:单个字段的索引
- 复合索引:多个字段的组合索引
- 多键索引:数组字段的索引
- 文本索引:用于全文搜索
- 地理空间索引:用于地理位置查询
- 哈希索引:基于字段值的哈希
javascript
// 创建单字段索引
db.users.createIndex({ name: 1 })
// 创建复合索引
db.users.createIndex({ age: 1, name: -1 })
// 创建唯一索引
db.users.createIndex({ email: 1 }, { unique: true })
// 查看索引
db.users.getIndexes()
// 删除索引
db.users.dropIndex("name_1")副本集(Replica Set)
定义
副本集是一组维护相同数据集的 MongoDB 实例,提供冗余和高可用性。
成员角色
- Primary(主节点):处理所有写操作
- Secondary(从节点):复制主节点数据,可处理读操作
- Arbiter(仲裁节点):参与选举,不存储数据
选举机制
- 主节点故障时,从节点自动选举新主节点
- 需要多数节点存活才能选举
- 选举过程通常在几秒内完成
分片(Sharding)
定义
分片是将数据分布到多台服务器的过程,用于处理大规模数据和高吞吐量操作。
分片集群组件
- mongos:查询路由器,处理客户端请求
- config servers:配置服务器,存储集群元数据
- shards:分片服务器,存储实际数据
分片策略
- 范围分片(Range Sharding):基于分片键值范围
- 哈希分片(Hashed Sharding):基于分片键哈希值
数据模型设计
嵌入 vs 引用
嵌入文档(Embedding)
优点:
- 单次查询获取所有数据
- 原子性更新
- 更好的读取性能
适用场景:
- 一对一关系
- 一对少关系(子文档数量少)
- 经常一起查询的数据
javascript
// 嵌入示例
{
"user": "张三",
"address": {
"city": "北京",
"street": "长安街"
}
}引用(Referencing)
优点:
- 避免数据重复
- 数据一致性
- 文档大小可控
适用场景:
- 一对多关系(子文档数量多)
- 多对多关系
- 经常独立查询的数据
javascript
// 引用示例
// users 集合
{ "_id": 1, "name": "张三" }
// orders 集合
{ "_id": 101, "user_id": 1, "amount": 100 }总结
理解 MongoDB 的核心概念是掌握 MongoDB 的基础:
- 数据库:集合的容器
- 集合:文档的容器,无固定模式
- 文档:BSON 格式的基本数据单元
- 字段:文档的键值对
- _id:文档的唯一标识符
- 索引:提高查询效率的数据结构
- 副本集:提供高可用性
- 分片:支持水平扩展
在下一章中,我们将学习 MongoDB 数据建模。