外观
MongoDB 笔记
约 2679 字大约 9 分钟
2025-08-22
一、MongoDB 简介
1.1 什么是 MongoDB?
MongoDB 是一款基于分布式文件存储的开源 NoSQL 数据库,由 C++ 语言编写。它旨在为 Web 应用提供可扩展的高性能数据存储解决方案。MongoDB 将数据存储为文档,这些文档以类似 JSON 的 BSON(Binary JSON)格式存储,使数据结构非常灵活。
1.2 MongoDB 核心特点
- 高性能:内存计算,数据读写速度快
- 高可用性:支持自动故障转移和数据复制
- 易扩展性:支持水平扩展(分片),轻松处理海量数据
- 灵活的数据模型:动态模式,无需预先定义表结构
- 丰富的查询语言:支持复杂的查询和聚合操作
- 内置地理空间索引:支持地理空间查询
1.3 MongoDB 与关系型数据库对比
| 术语 | MongoDB | 关系型数据库 |
|---|---|---|
| 数据库 | database | database |
| 集合 | collection | table |
| 文档 | document | row |
| 字段 | field | column |
| 主键 | _id | primary key |
关键区别:
- MongoDB 是文档型数据库,无固定表结构
- MongoDB 使用 BSON 格式存储数据,支持嵌套文档
- MongoDB 没有表连接(JOIN)操作
- MongoDB 通常不支持多文档事务(4.0+版本开始支持)
1.4 典型应用场景
- 实时分析:快速处理和分析大量数据
- 内容管理系统:存储灵活的文档结构
- 移动应用后端:处理大量用户生成的内容
- 物联网数据存储:处理高吞吐量的传感器数据
- 缓存:作为传统数据库的缓存层
二、环境搭建
2.1 安装 MongoDB
Windows:
- 下载 MongoDB 安装包
- 运行安装程序
- 创建数据目录:
D:\Programs\MongoDB\data - 创建日志目录:
D:\Programs\MongoDB\logs - 安装服务:
mongod --install --dbpath D:\Programs\MongoDB\data --logpath D:\Programs\MongoDB\logs\mongoDB.log
Linux:
# Ubuntu/Debian
sudo apt-get install -y mongodb-org
# CentOS
sudo yum install -y mongodb-org2.2 启动与连接
启动服务:
# Windows
net start MongoDB
# Linux
sudo systemctl start mongod连接 MongoDB:
# 无认证连接
mongo
# 带认证连接
mongo -u username -p password --authenticationDatabase admin
# 连接特定数据库
mongo localhost:27017/database_name三、核心概念
3.1 数据库(Database)
MongoDB 中的数据库类似于关系型数据库中的数据库,用于组织和隔离不同的应用数据。
常用操作:
// 查看所有数据库
show dbs
// 切换/创建数据库
use mydb
// 查看当前数据库
db
// 删除当前数据库
db.dropDatabase()系统数据库:
admin:根用户数据库,存储用户、角色权限等信息local:存储本地数据,不会被复制config:用于分片配置
3.2 集合(Collection)
集合是 MongoDB 中文档的容器,类似于关系型数据库中的表。
常用操作:
// 查看当前数据库中的集合
show collections
// 创建集合
db.createCollection("users")
// 删除集合
db.users.drop()特点:
- 无需预先定义集合结构
- 集合名不能包含空字符和系统保留字符
- 集合名不能以"system."开头(系统集合)
3.3 文档(Document)
文档是 MongoDB 中的基本数据单元,以 BSON 格式存储。
文档特点:
- 键值对结构,类似 JSON 对象
- 键是字符串
- 值可以是多种数据类型
- 每个文档都有一个
_id字段作为唯一标识
示例:
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"name": "John Doe",
"age": 30,
"email": "john@example.com",
"address": {
"street": "123 Main St",
"city": "New York"
},
"hobbies": ["reading", "swimming"]
}3.4 ObjectId
ObjectId 是 MongoDB 默认的文档 ID 生成策略,是一个 12 字节的 BSON 类型:
- 4 字节:时间戳
- 3 字节:机器标识码
- 2 字节:进程 ID
- 3 字节:计数器
特点:
- 保证全局唯一性
- 包含创建时间信息
- 按时间有序排列
四、基本操作
4.1 文档插入
// 插入单个文档
db.users.insertOne({
name: "Alice",
age: 25,
email: "alice@example.com"
})
// 插入多个文档
db.users.insertMany([
{name: "Bob", age: 30, email: "bob@example.com"},
{name: "Charlie", age: 35, email: "charlie@example.com"}
])4.2 文档查询
// 查询所有文档
db.users.find()
// 格式化输出
db.users.find().pretty()
// 条件查询
db.users.find({age: 30}) // age等于30
db.users.find({age: {$gt: 25}}) // age大于25
db.users.find({age: {$in: [25, 30]}}) // age在25或30中
// AND 条件
db.users.find({age: 30, name: "Bob"})
// OR 条件
db.users.find({
$or: [{age: 25}, {name: "Charlie"}]
})
// 模糊查询
db.users.find({name: /li/}) // name包含"li"4.3 文档更新
// 更新单个文档
db.users.updateOne(
{name: "Alice"},
{$set: {age: 26}}
)
// 更新多个文档
db.users.updateMany(
{age: {$lt: 30}},
{$inc: {age: 1}} // age增加1
)
// 替换整个文档(保留_id)
db.users.replaceOne(
{name: "Bob"},
{name: "Robert", age: 31, email: "robert@example.com"}
)
// upsert:存在则更新,不存在则插入
db.users.updateOne(
{name: "David"},
{$set: {age: 28}},
{upsert: true}
)4.4 文档删除
// 删除单个文档
db.users.deleteOne({name: "Charlie"})
// 删除多个文档
db.users.deleteMany({age: {$lt: 30}})
// 删除所有文档(保留集合结构)
db.users.deleteMany({})五、高级查询
5.1 排序与分页
// 排序(1升序,-1降序)
db.users.find().sort({age: 1, name: -1})
// 分页
db.users.find().skip(10).limit(10) // 跳过10条,取10条
// 组合使用
db.users.find({age: {$gt: 25}})
.sort({age: -1})
.skip(0)
.limit(5)5.2 投影(字段选择)
// 只返回指定字段
db.users.find({}, {name: 1, email: 1}) // 1表示包含
// 排除_id字段
db.users.find({}, {_id: 0, name: 1, email: 1})
// 排除特定字段
db.users.find({}, {age: 0}) // 返回除age外的所有字段5.3 数组操作
// 创建包含数组的文档
db.users.insertOne({
name: "Eve",
hobbies: ["reading", "swimming", "coding"]
})
// 查询数组包含特定值的文档
db.users.find({hobbies: "swimming"})
// 查询数组长度
db.users.find({hobbies: {$size: 3}})
// 数组元素更新
db.users.updateOne(
{name: "Eve"},
{$push: {hobbies: "traveling"}} // 添加元素
)
db.users.updateOne(
{name: "Eve"},
{$pop: {hobbies: 1}} // 移除最后一个元素
)
db.users.updateOne(
{name: "Eve"},
{$pull: {hobbies: "swimming"}} // 移除特定元素
)5.4 嵌套文档查询
// 创建嵌套文档
db.users.insertOne({
name: "Frank",
address: {
street: "456 Oak St",
city: "Boston",
zip: "02108"
}
})
// 查询嵌套字段
db.users.find({"address.city": "Boston"})
// 更新嵌套字段
db.users.updateOne(
{name: "Frank"},
{$set: {"address.zip": "02110"}}
)六、聚合查询
6.1 聚合框架基础
聚合框架是 MongoDB 中强大的数据处理工具,类似于 SQL 中的 GROUP BY。
// 基本语法
db.collection.aggregate([
{ $stage1: { ... } },
{ $stage2: { ... } },
...
])6.2 常用聚合操作符
// $match:过滤文档
db.users.aggregate([
{ $match: { age: { $gt: 25 } } }
])
// $group:分组统计
db.users.aggregate([
{ $group: {
_id: "$age",
count: { $sum: 1 },
avgAge: { $avg: "$age" }
}}
])
// $sort:排序
db.users.aggregate([
{ $sort: { age: -1 } }
])
// $project:重塑文档结构
db.users.aggregate([
{ $project: {
name: 1,
age: 1,
status: {
$cond: {
if: { $gt: ["$age", 30] },
then: "senior",
else: "junior"
}
}
}}
])
// $limit 和 $skip:分页
db.users.aggregate([
{ $skip: 10 },
{ $limit: 10 }
])6.3 聚合实例
计算每个年龄段的人数:
db.users.aggregate([
{
$group: {
_id: "$age",
count: { $sum: 1 }
}
},
{
$sort: { _id: 1 }
}
])查找最受欢迎的爱好:
db.users.aggregate([
{ $unwind: "$hobbies" },
{
$group: {
_id: "$hobbies",
count: { $sum: 1 }
}
},
{
$sort: { count: -1 }
},
{
$limit: 5
}
])七、索引
7.1 索引基础
索引可以显著提高查询性能,但会增加写操作的开销和存储空间。
常用索引类型:
- 单字段索引:在单个字段上创建的索引
- 复合索引:在多个字段上创建的索引
- 唯一索引:确保索引字段的值唯一
- 文本索引:支持文本搜索
- 地理空间索引:支持地理位置查询
7.2 索引操作
// 创建单字段索引
db.users.createIndex({name: 1}) // 1表示升序,-1表示降序
// 创建唯一索引
db.users.createIndex({email: 1}, {unique: true})
// 创建复合索引
db.users.createIndex({name: 1, age: -1})
// 创建文本索引
db.articles.createIndex({content: "text"})
// 查看集合索引
db.users.getIndexes()
// 查看索引大小
db.users.totalIndexSize()
// 删除索引
db.users.dropIndex("name_1")
db.users.dropIndexes() // 删除所有索引7.3 索引优化
为常用查询条件创建索引
// 如果经常按name和age查询 db.users.createIndex({name: 1, age: -1})遵循左前缀原则
// 复合索引 {a: 1, b: 1, c: 1} // 有效:a, a+b, a+b+c // 无效:b, c, b+c使用覆盖索引
// 索引包含查询和返回的所有字段 db.users.createIndex({name: 1, age: 1}) db.users.find({name: "Alice"}, {name: 1, age: 1, _id: 0})分析查询性能
// 使用explain分析查询 db.users.find({name: "Alice"}).explain("executionStats")
八、安全与权限
8.1 用户管理
// 切换到admin数据库
use admin
// 创建管理员用户
db.createUser({
user: "admin",
pwd: "password123",
roles: [{role: "root", db: "admin"}]
})
// 创建普通用户
use mydb
db.createUser({
user: "user1",
pwd: "password123",
roles: [{role: "readWrite", db: "mydb"}]
})
// 修改密码
db.changeUserPassword("user1", "newpassword")
// 删除用户
db.dropUser("user1")8.2 内置角色
| 角色类型 | 角色 | 说明 |
|---|---|---|
| 数据库用户角色 | read | 提供读取所有非系统集合上数据的能力 |
| readWrite | 包含read所有权限及修改所有非系统集合上数据的能力 | |
| 数据库管理角色 | dbAdmin | 提供执行管理任务的能力 |
| userAdmin | 提供在当前数据库上创建和修改角色和用户的能力 | |
| dbOwner | 结合了readWrite、dbAdmin和userAdmin的权限 | |
| 集群管理角色 | clusterAdmin | 提供最强大的集群管理访问 |
| 备份恢复角色 | backup | 提供备份权限 |
| restore | 提供恢复权限 | |
| 所有数据库角色 | readAnyDatabase | 读取所有数据库 |
| readWriteAnyDatabase | 读写所有数据库 |
8.3 启用认证
创建管理员用户(如上所示)
修改配置文件(mongod.conf):
security: authorization: enabled重启 MongoDB 服务
连接时认证:
mongo -u admin -p password123 --authenticationDatabase admin
九、最佳实践
9.1 数据建模
嵌入 vs 引用:
- 关系紧密、一起读取的数据:使用嵌入文档
- 关系松散、独立访问的数据:使用引用
避免大文档:
- 单个文档大小限制为 16MB
- 大型数据考虑拆分或使用 GridFS
合理设计_id:
- 默认 ObjectId 通常足够
- 可自定义_id提高查询效率
9.2 性能优化
索引策略:
- 为常用查询条件创建索引
- 避免过多索引影响写性能
- 定期分析慢查询
查询优化:
- 只查询需要的字段
- 合理使用投影
- 避免全集合扫描
批量操作:
// 批量插入 db.users.insertMany([...]) // 批量更新 db.users.bulkWrite([...])
9.3 高可用与扩展
副本集:
- 至少3个节点(1主2从)
- 自动故障转移
- 数据冗余
分片集群:
- 适用于海量数据
- 水平扩展
- 需要配置分片键
备份策略:
- 定期使用
mongodump备份 - 结合 oplog 实现增量备份
- 定期验证备份可用性
- 定期使用
十、实用技巧
10.1 常用管理命令
// 查看数据库状态
db.stats()
// 查看集合状态
db.users.stats()
// 查看当前连接
db.currentOp()
// 杀死操作
db.killOp(opid)
// 修复数据库
db.repairDatabase()
// 查看帮助
db.help()
db.users.help()10.2 数据导入导出
导出数据:
# 导出JSON
mongoexport --db mydb --collection users --out users.json
# 导出CSV
mongoexport --db mydb --collection users --type=csv --fields=name,age,email --out users.csv导入数据:
# 导入JSON
mongoimport --db mydb --collection users --file users.json
# 导入CSV
mongoimport --db mydb --collection users --type=csv --headerline --file users.csv备份整个数据库:
mongodump --db mydb --out backup/恢复数据库:
mongorestore --db mydb backup/mydb/