Skip to content

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 字符串
Integer42整数值
Double3.14浮点数
Booleantrue布尔值
DateISODate(...)日期时间
Nullnull空值
Array[1, 2, 3]数组
Object{a: 1}嵌套文档
ObjectIdObjectId(...)12 字节唯一 ID
Binary DataBinData(...)二进制数据
TimestampTimestamp(...)时间戳

_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 的基础:

  1. 数据库:集合的容器
  2. 集合:文档的容器,无固定模式
  3. 文档:BSON 格式的基本数据单元
  4. 字段:文档的键值对
  5. _id:文档的唯一标识符
  6. 索引:提高查询效率的数据结构
  7. 副本集:提供高可用性
  8. 分片:支持水平扩展

在下一章中,我们将学习 MongoDB 数据建模