Appearance
MongoDB 基础概念
MongoDB是一个面向文档的NoSQL数据库,它使用文档(documents)来存储数据,这些文档采用BSON(Binary JSON)格式。了解MongoDB的基础概念对于有效使用这个数据库至关重要。
文档(Document)
文档是MongoDB中的基本数据单元,类似于关系数据库中的行。文档使用键值对存储数据,格式类似于JSON。
文档结构
json
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"name": "张三",
"age": 25,
"email": "zhangsan@example.com",
"address": {
"street": "中山路123号",
"city": "北京",
"zipcode": "100000"
},
"hobbies": ["读书", "游泳", "编程"],
"isActive": true,
"registeredDate": ISODate("2023-01-01T00:00:00Z")
}
文档特点
- 动态模式:同一集合中的文档可以有不同的字段
- 嵌套结构:文档可以包含子文档和数组
- 唯一标识符:每个文档都有一个唯一的
_id字段 - BSON类型:支持丰富的数据类型
_id字段
每个文档都有一个名为_id的主键字段,其值在集合中必须唯一:
javascript
// 自动生成的ObjectId
_id: ObjectId("507f1f77bcf86cd799439011")
// 自定义_id值
_id: "custom-id-123"
_id: 12345
_id: UUID("5e8d4e8d-1b3a-4c2d-8e9f-0a1b2c3d4e5f")
集合(Collection)
集合是文档的分组,类似于关系数据库中的表。集合具有以下特点:
集合特征
- 动态模式:集合中的文档可以有不同的结构
- 命名空间:集合名称在数据库中必须唯一
- 自动创建:当第一次插入文档时,集合会被自动创建
- 无模式定义:不需要预先定义集合的结构
集合命名规则
- 集合名称不能以"system."开头
- 集合名称不能包含保留字符"$"
- 集合名称不能为空字符串
示例
javascript
// 创建集合并插入文档
db.users.insertOne({
name: "王五",
email: "wangwu@example.com"
});
db.products.insertMany([
{ name: "笔记本电脑", price: 5999, category: "电子产品" },
{ name: "鼠标", price: 99, category: "电子产品" }
]);
数据库(Database)
数据库是集合的容器,MongoDB支持多个数据库。
数据库特点
- 物理隔离:不同数据库的数据文件相互隔离
- 逻辑分组:用于组织相关集合
- 权限控制:可以在数据库级别设置权限
常用数据库
javascript
// 系统数据库
admin // 根用户、角色和特权
local // 分片和副本集配置
config // 分片集群配置
// 用户数据库
myApp // 应用程序数据库
test // 测试数据库
BSON数据类型
MongoDB使用BSON(Binary JSON)格式存储文档。BSON扩展了JSON,支持更多数据类型:
基本类型
| 类型 | JSON | BSON | 示例 |
|---|---|---|---|
| 字符串 | String | String | "hello" |
| 整数 | Number | Int32/Int64 | 42 |
| 双精度 | Number | Double | 3.14 |
| 布尔值 | Boolean | Boolean | true/false |
| 数组 | Array | Array | [1, 2, 3] |
| 文档 | Object | Object |
特殊类型
| 类型 | BSON | 描述 | 示例 |
|---|---|---|---|
| ObjectId | ObjectId | 文档唯一标识符 | ObjectId("...") |
| 日期 | Date | UTC时间 | ISODate("...") |
| 正则表达式 | RegExp | 模式匹配 | /pattern/i |
| null | Null | 空值 | null |
| 二进制数据 | BinData | 二进制数据 | BinData(...) |
| 代码 | Code | JavaScript代码 | function(){} |
| 符号 | Symbol | 特定语言字符串 | Symbol("str") |
命名空间
命名空间是数据库名称和集合名称的组合,格式为database.collection:
javascript
// 命名空间示例
myApp.users // myApp数据库中的users集合
blog.posts // blog数据库中的posts集合
shop.products // shop数据库中的products集合
索引(Index)
索引提高了查询性能,类似于书籍的目录。
索引类型
- 单字段索引:基于单个字段的索引
- 复合索引:基于多个字段的索引
- 多键索引:基于数组字段的索引
- 文本索引:用于文本搜索
- 地理空间索引:用于地理位置查询
创建索引
javascript
// 单字段索引
db.users.createIndex({ email: 1 })
// 复合索引
db.orders.createIndex({ userId: 1, orderDate: -1 })
// 唯一索引
db.users.createIndex({ email: 1 }, { unique: true })
GridFS
GridFS是MongoDB用来存储大型文件的规范,将文件分割成较小的块进行存储。
GridFS特点
- 存储大于16MB的文件
- 文件被分割成255KB的块
- 提供文件元数据存储
- 支持断点续传
原子性和事务
单文档原子性
MongoDB保证单个文档的所有写操作都是原子的。
多文档事务
从MongoDB 4.0开始支持多文档ACID事务:
javascript
// 4.0+版本的多文档事务
const session = client.startSession();
session.withTransaction(async () => {
await db.accounts.updateOne(
{ name: "张三" },
{ $inc: { balance: -100 } }
);
await db.accounts.updateOne(
{ name: "李四" },
{ $inc: { balance: 100 } }
);
});
副本集(Replica Set)
副本集是一组维护相同数据集的mongod实例,提供冗余和高可用性。
副本集组成
- 主节点(Primary):处理所有写操作
- 从节点(Secondary):复制主节点的数据
- 仲裁节点(Arbiter):参与选举,不存储数据
分片(Sharding)
分片是将数据分布在多个机器上的方法,用于处理大量数据和高吞吐量操作。
分片组件
- 分片(Shard):存储数据子集
- 配置服务器(Config Servers):存储集群元数据
- mongos:查询路由器
连接池
MongoDB驱动程序使用连接池来管理与数据库的连接:
javascript
const options = {
maxPoolSize: 10, // 最大连接数
minPoolSize: 5, // 最小连接数
maxIdleTimeMS: 30000, // 最大空闲时间
serverSelectionTimeoutMS: 5000, // 服务器选择超时
socketTimeoutMS: 45000 // 套接字超时
};
总结
MongoDB的基础概念构成了理解和使用这个数据库的基石。文档、集合和数据库是MongoDB数据模型的核心组件,而索引、原子性、副本集和分片等概念则是构建高性能、高可用性应用的关键要素。掌握这些概念有助于更好地设计MongoDB应用程序。