一、MongoDB 基础概念
1. 什么是 MongoDB
- MongoDB 是一个文档型数据库,数据以类似 JSON 的文档形式存储,使用 BSON 格式。
- 设计理念是应对大数据量1、高性能和灵活性需求。
- 数据组织方式:数据库→2集合→文档,其中集合类似于关系型数据库的表,文档类似于行。
2. 主要特点
3456- 文档导向存储:以 JSON-like 格式存储,数据结构灵活。
- 索引优化查询:7可对任意属性创建索引,提升查询效率。
- *数据镜像与扩展性8*:通过副本集实现数据冗余和高可用。
- 水平扩展与分片9:利用分片技术将数据分布到多个节点。
- 强大的查询语言10:支持复杂查询表达式,包括内嵌对象和数组查询。
- 灵活的数据更新11:使用 update () 命令可替换整个文档或更新指定字段。
- MapReduce1213批量处理:用于大规模数据处理和聚合操作,Map 和 Reduce 函数用 JavaScript 编写。
- GridFS 大文件1415存储:存储和检索大于 BSON 文档大小限制的文件。
- 多语言支持:支16持 RUBY、PYTHON、JAVA 等多种编程语言。
3. 核心概念对3比
SQL 术语 / 概念 | MongoDB 术语 / 概念 | 解释 / 说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表 / 集合 |
row | document | 数据记录行 / 文档 |
column | field | 数据字段 / 域 |
index | index | 索引 |
primary key | primary key | 主键,MongoDB 自动将_id 字段设置为主键 |
table joins | - | 表连接,MongoDB 不支持 |
二、MongoDB 安装与启动
1. 安装前准备
- 安装 Linux 平台依赖包:
dnf install libcurl openssl -y
。 - 下载 MongoDB 安装17包并解压:
tar -zxvf mongodb-linux-x86_64-rhel8-8.0.8.tgz
。 - 将解压包拷贝到指定目录18:
mv mongodb-linux-x86_64-rhel88-8.0.8 /usr/local/mongodb
。
2. 配置环境变19量
- 将 MongoDB 可执行文件添加到 PATH 路径:
echo 'export PATH=/usr/local/mongodb/bin:$PATH' > /etc/profile
source /etc/profile
3. 创建数据库目20录
- 数据存储目录:
/var/lib/mongodb
。 - 日志文件目录:
/va{insert\_element\_16\_}r/log/mongodb
。 - 创建目录并设置权限:
22```bash
mkdir -p /var/lib/mongo
mkdir -p /var/log/mongodb
chown whoami /var/lib/mongo
chown whoami /var/log/mongodb
### 4. 编译安装Op{insert\_element\_18\_}enSSL11
- 安装编译工具:`dnf install -y gcc make perl`。
- 配置、编译和安装Ope{insert\_element\_19\_}nSSL:
```bash
tar xzf openssl-1.1.w.tar.gz
cd openssl-1.1.1w
./config -prefix=/opt/openssl11 --openssldir=/opt/openssl/ssl
make -j$(nproc)
make install
5. 设置 Open24SSL11 环境变量
echo 'export LD_LIBRARY_PATH=/opt/openssl11/lib:$LD_LIBRARY_PATH' | sudo tee /etc/profile.d/openssl11.sh
source /etc/profile.d/openssl11.sh
6. 启动 Mong25oDB 服务
mongod --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --fork
启动成功后会显示子进程启动信26息。
三、MongoDB27 Shell 使用
1. 安装 MongoDB Shell
- 解压安装包并复制 mongosh 二进制文件到 PATH 目录:
tar xzf mongosh-2.5.0-linux-x64-openssl3.tgz
cd mongosh-2.5.0-linux-x64-openssl3/bin
cp mongosh /usr/local/bin/
cp mongosh_crypt_v1.so /usr/local/lib/
2. 连接 Mong28oDB 服务器
- 基本连接命令:
mongosh --host <hostname> --port <port>
。 - 默认连接本地服务器:
{insert\_element\_25\_}mongosh
,成功连接后会显示 MongoDB 和 mongosh 版本信息。
四、数据库管理、
1. 查看数据库
- 查看所有数据库:
show dbs
。 - 查看当前使用的数据库:31
db
。
2. 创建数据库32
- 使用
use DATABASE_NAME
命令,若数据库不存在则自动创建。 - 示例:
use runoob
switched to db runoob
3. 删除数据库
34- 使用db.dropDatabase()
方法。
- 示例:
use myDatabase
db.dropDatabase()
4. 默认与系统数36据库
- 默认数据库:test,未指定数据库时数据默认存储在此。
- 系统内置数据库37:
- admin:存储用户身份信息和全局权限。
- config:分片38集群中存储分片元数据。
- local:存储当39前节点的副本集状态和操作日志。
五、集合管理
1. 查看集合
- 使用
show collections
或show tables
命令。
2. 创建集合
41- 使用db.createCollection(name, options)
方法。
- 示例:创建固定大小集合
db.createCollection("myComplexCollection", {
capped: true,
size: 10485760,
max: 5000,
validator: {
$jsonSchema: {
required: ["name", "email"],
bsonType: "object",
properties: {
name: { bsonType: "string" },
email: { bsonType: "string", pattern: ".+@.+" }
}
}
},
validationLevel: "strict",
storageEngine: { wiredTiger: { configString: "block_compressor=zstd" } }
})
3. 重命名集合
43- 使用db.adminCommand({ renameCollection: "sourceDb.sourceCollection", to: "targetDb.targetCollection" })
。
4. 删除集合
44- 使用db.collection.drop()
方法。
六、文档操作
1. 插入文档
- insertOne():插入单个文档。
javascri{insert_element_42_}pt
db.myCollection.insertOne({ name: "Alice", age: 25, city: "New York" })
- insertMany():插入多个文档。
javascri{insert_element_43_}pt
db.myCollection.insertMany([ { name: "Bob", age: 30, city: "Los Angeles" }, { name: "Charlie", age: 35, city: "Chicago" } ])
2. 查询文档
- find():查找多个文档。
- 查找所有:
db.{insert\_element\_44\_}myCollection.find()
。 - 按条件查找:
db.myCollection.find({ age: { $gt: 25 } })
。
- 查找所有:
- findOne()49:查找单个文档。
db.myCollection.findOne({ name: "Alice" })
3. 删除文档
- deleteOne():删除单个匹配文档。
db.myCollection.deleteOne({ name: "Alice" })
- deleteMany():删除所有匹配文档。
db.myCollection.deleteMany({ name: "Bob" })
4. 更新文档
- updateOne():更新单个匹配文档。
db.myCollection.updateOne({ name: "Alice" }, { $set: { age: 26 } })
- updateMany():更新所有匹配文档。
db.myCollection.updateMany({ age: { $lt: 30 } }, { $set: { status: "active" } })
- replaceOne():替换单个匹配文档。
db.myCollection.replaceOne({ name: "Bob" }, { name: "Bob", age: 31 })
七、MongoDB 备份与恢复
1. 安装备份与恢复工具
rpm -ivh mongodb-database-tools-rhel70-x86_64-100.12.0.rpm
2. 数据备份(m56ongodump)
- 基本命令:
mongodump -h dbhost -d dbname -o dbdirectory
。 - 示例:备份所有数据到当57前目录下的 dump 目录
mongodump
3. 数据恢复(m58ongorestore)
- 基本命令:
mongorestore -h <hostname>:<port> -d dbname <path>
。 - 示例:从默认 dump 目59录恢复数据
mongorestore
八、用户管理
1. 创建用户
db.createUser({
user: "testuser",
pwd: "password123",
roles: [
{ role: "readWrite", db: "database_name" },
{ role: "dbAdmin", db: "database_name" }
]
})
2. 验证用户
### 3. 启用身份验证{insert\_element\_58\_}
- 编辑配置文件`mongod.conf`,添加:
```yaml
security:
authorization: "enabled"
- 或在启动命令中添加
--{insert\_element\_59\_}auth
参数。
4. 使用用户登录
mongosh --host hostname --port port -u "testuser" -p "password123" --authenticationDatabase "database_name"
5. 删除用户
{insert\_element\_62\_}
九、索引管理
1. 索引基础
- 索引作用:优化查询性能,基于集合字段创建数据结构。
- 创建索引:
d{insert\_element\_0\_}b.collection.createIndex( { field: 1 }, { options } )
,1 为升序,-1 为降序。 - 唯一索引:
db.users.createIndex( { email: 1 }, { unique: true } )
,确保字段值唯一。
2. 复合索引
- 基于多个字段创建索引,语法:
db.collection.createIndex( { field1: 1, field2: -1 } )
。 - 注意:查询条件需包含索引前缀字段才能有效利用复合索引。
3. 索引查看与删除
- 查看所有索引:
db.collection.getIndexes()
。 - 删除指定索引:
db.collection.dropIndex( "indexName" )
。 - 删除所有索引:
db.collection.dropIndexes()
。
4. 地理空间索引
- 用于地理位置相关查询,创建 2dsphere 索引:
db.places.createIndex( { location: "2dsphere" } )
。 - 查询示例:查找半径 5 公里内的地点:
db.places.find( {
location: {
$near: {
$geometry: { type: "Point", coordinates: [116.4074, 39.9042] },
$maxDistance: 5000
}
}
} )
十、聚合框架(Aggregation Framework)
1. 聚合管道概念
- 通过多个阶段(stage)处理数据,每个阶段对文档进行转换。
- 常见阶段:、group、、sort、$limit 等。
2. 基本聚合操作
- $match:过滤文档,类似 find 的查询条件:
db.sales.aggregate( [ { $match: { category: "electronics", price: { $gt: 100 } } } ] )
- $group:分组聚合,_id 指定分组字段,可使用聚合表达式:
db.sales.aggregate( [ { $group: { _id: "$category", totalSales: { $sum: "$price" } } } ] )
- $project:投影字段,控制输出内容:
db.sales.aggregate( [ { $project: { product: 1, price: 1, discount: { $multiply: [ "$price", 0.8 ] } } } ] )
3. 高级聚合操作
- $lookup:左关联查询,类似 SQL 的 LEFT JOIN:
db.orders.aggregate( [ { $lookup: { from: "customers", localField: "customerId", foreignField: "_id", as: "customerInfo" } } ] )
- $unwind:展开数组字段,将每个数组元素转为独立文档:
db.products.aggregate( [ { $unwind: "$tags" } ] )
4. 聚合表达式
- 数学表达式:、avg、、max。
- 条件表达式:、ifNull、$switch。
- 字符串表达式:、substr、$toUpper。
十一、分片集群(Sharding)
1. 分片架构组件
- 分片节点(Shard):存储实际数据,可由副本集组成。
- 配置服务器(Config Server):存储分片元数据(如数据分布信息)。
- 路由节点(MongoS):客户端连接入口,负责转发请求到对应分片。
2. 分片部署步骤
- 启动配置服务器:
mongod --configsvr --dbpath /data/config --port 27019
。 - 启动分片节点(副本集):
mongod --shardsvr --dbpath /data/shard1 --port 27017 --replSet rs1 mongod --shardsvr --dbpath /data/shard2 --port 27018 --replSet rs1
- 初始化副本集:
rs.initiate()
。 - 启动路由节点:
mongos --configdb configServerHost:27019
。 - 将分片添加到集群:
sh.addShard( "rs1/host1:27017,host2:27018" )
。 - 启用分片:
sh.enableSharding( "databaseName" )
。 - 设置分片键:
sh.shardCollection( "databaseName.collectionName", { shardKey: 1 } )
。
3. 分片键选择
- 范围分片键:如时间字段,数据按范围分布,适合时序数据。
- 哈希分片键:如用户 ID 的哈希值,数据均匀分布,适合高并发写入。
- 复合分片键:如 {region: 1, date: 1},结合范围和哈希优势。
十二、副本集(Replica Set)
1. 副本集架构
- 主节点(Primary):处理所有写入操作,同步数据到从节点。
- 从节点(Secondary):复制主节点数据,处理读请求。
- 仲裁节点(Arbiter):不存储数据,仅参与选举决策。
2. 副本集初始化
// 连接到主节点
mongosh --port 27017
// 定义副本集配置
config = {
_id: "rs0",
members: [
{ _id: 0, host: "server1:27017" },
{ _id: 1, host: "server2:27017" },
{ _id: 2, host: "server3:27017", arbiterOnly: true }
]
}
// 初始化副本集
rs.initiate( config )
3. 故障转移与读偏好
- 自动故障转移:主节点故障时,从节点通过选举产生新主节点。
- 读偏好(Read Preference):
- primary:只从主节点读取(默认)。
- primaryPreferred:优先从主节点读取,不可用时从从节点。
- secondary:只从从节点读取。
- secondaryPreferred:优先从从节点读取,不可用时从主节点。
- nearest:从最近的节点读取。
十三、事务管理
1. 事务特性
- ACID 特性:MongoDB 4.0 + 支持分布式事务,确保原子性、一致性、隔离性、持久性。
- 多文档事务:跨文档、跨集合、跨数据库的操作作为原子单元。
2. 事务使用示例
// 开始事务
const session = db.getMongo().startSession();
try {
session.startTransaction();
// 操作1:更新账户A余额
db.accounts.updateOne(
{ _id: "A" },
{ $inc: { balance: -100 } },
{ session }
);
// 操作2:更新账户B余额
db.accounts.updateOne(
{ _id: "B" },
{ $inc: { balance: 100 } },
{ session }
);
// 提交事务
await session.commitTransaction();
console.log("转账成功");
} catch (error) {
// 回滚事务
await session.abortTransaction();
console.error("转账失败:", error);
} finally {
session.endSession();
}
3. 事务注意事项
- 事务超时时间默认 60 秒,可通过
maxTransactionTimeMS
参数调整。 - 分片集群中事务需使用 MongoDB 4.2+,且配置服务器为副本集。
- 避免长事务,减少锁竞争。
十四、存储引擎
1. WiredTiger(默认)
- 特点:支持文档级锁、压缩、加密,性能均衡,适合大多数场景。
- 压缩算法:
- zlib:压缩率高,CPU 消耗大。
- snappy:压缩率低,速度快。
- zstd:平衡压缩率和速度(默认)。
- 配置示例:在 mongod.conf 中设置
storage.wiredTiger.engineConfig.compressor = zstd
。
2. MMAPv1(旧版)
- 特点:使用文件映射内存,支持表级锁,不推荐新部署。
- 适用场景:遗留系统兼容,或需要特定功能(如稀疏集合)。
3. In-Memory
- 特点:数据全部存储在内存,适合对响应时间要求极高的场景。
- 注意:重启后数据丢失,需搭配持久化存储。
十五、监控与性能调优
1. 内置监控命令
- 查看服务器状态:
db.serverStatus()
,获取内存、CPU、IO 等指标。 - 查看当前操作:
db.currentOp()
,查看正在执行的命令。 - 慢查询日志:启用慢查询日志(默认超过 100ms):
bash
mongod --slowms 50 --logpath /var/log/mongodb/mongod.log
2. 性能调优策略
- 索引优化:为频繁查询的字段创建索引,避免全表扫描。
- 批量操作:使用 insertMany、bulkWrite 替代单条插入,减少网络开销。
- 连接池优化:调整驱动程序的连接池大小,默认值通常足够。
- 内存配置:WiredTiger 存储引擎建议将 50% 物理内存分配给缓存。
- 磁盘 IO:使用 SSD 存储数据,避免频繁写入导致磁盘瓶颈。
3. 监控工具
- MongoDB Compass:图形化工具,查看性能指标和查询分析。
- MongoDB Atlas:云服务自带监控仪表盘。
- Prometheus + Grafana:通过 MongoDB Exporter 采集指标并可视化。
十六、应用场景
1. 内容管理系统
- 灵活的数据结构适合存储博客、文章等内容,支持动态字段扩展。
- 案例:WordPress 插件、新闻门户网站。
2. 实时数据分析
- 聚合框架和 MapReduce 支持快速处理海量数据,如用户行为分析。
- 案例:电商平台商品浏览统计、广告点击分析。
3. 物联网(IoT)数据存储
- 分片集群支持海量设备数据存储,时间序列数据查询优化。
- 案例:智能家居设备日志、工业传感器数据采集。
4. 社交网络应用
- 文档模型适合存储用户关系、动态等复杂结构,支持高并发读写。
- 案例:社交平台消息系统、用户资料管理。
5. 移动应用后端
- 多语言驱动和云服务(MongoDB Atlas)简化移动应用开发。
- 案例:移动游戏进度存储、社交 APP 用户数据。
十七、最佳实践
1. 数据模型设计
- 嵌入 vs 引用:
- 多对一关系:嵌入子文档(如用户包含地址)。
- 多对多关系:使用引用 + 索引(如用户与角色关联)。
- 避免过度规范化:适当冗余字段减少查询关联。
2. 安全配置
- 启用身份验证,分配最小权限角色。
- 禁止公网直接访问 MongoDB 服务,使用 VPN 或防火墙限制。
- 启用 TLS/SSL 加密通信:
mongod --ssl --sslCertificateKeyFile cert.pem
。
3. 备份与恢复策略
- 定期全量备份(如每天)+ 增量备份(如每小时)。
- 测试备份恢复流程,确保数据可恢复。
- 异地灾备,防止物理故障导致数据丢失。
4. 版本升级
- 先在测试环境验证新版本兼容性,尤其注意废弃功能。
- MongoDB 4.4 + 支持滚动升级,减少服务中断时间。
- 升级前备份数据,准备回滚方案。
十八、常见问题与解决方案
1. 性能问题排查
- 慢查询分析:使用
db.currentOp()
和慢查询日志定位问题查询。 - 索引缺失:检查查询是否使用索引,
explain()
分析执行计划。 - 锁竞争:查看
db.serverStatus().locks
,优化写入频率或分片。
2. 磁盘空间问题
- WiredTiger 预分配:使用
db.repairDatabase()
回收未使用空间。 - 删除过期数据:定期删除不再需要的历史数据,或使用 TTL 索引。
- 分片扩容:当单个分片数据量过大时,添加新分片并重新平衡数据。
3. 副本集异常
- 选举失败:确保多数节点可用(如 3 节点副本集至少 2 节点在线)。
- 数据不一致:使用
rs.syncFrom("primaryHost")
手动同步数据。 - 仲裁节点配置:奇数个节点或添加仲裁节点避免脑裂。
4. 事务相关问题
- 事务超时:优化事务内操作,减少执行时间或增加
maxTransactionTimeMS
。 - 并发冲突:使用乐观锁(如版本号字段)或调整隔离级别。