一些可以做翻译的网站百度官方网站下载
MongoDB基础知识
目录
- 基础篇
- 一、MongoDB入门指南(零基础必读)
- 二、MongoDB简介
- 三、MongoDB安装与配置
- 四、MongoDB基本操作
- 五、MongoDB查询操作
- 进阶篇
- 六、MongoDB索引
- 七、MongoDB聚合操作
- 八、MongoDB数据模型
- 九、MongoDB安全
- 十、MongoDB备份恢复
- 十一、MongoDB性能优化
- 十二、MongoDB高级特性
- 十三、MongoDB复制集
- 十四、MongoDB分片集群
- 应用篇
- 十五、MongoDB性能诊断
- 十六、MongoDB数据迁移
- 十七、MongoDB应用开发最佳实践
- 十八、MongoDB运维管理
- 十九、MongoDB常见应用场景示例
- 二十、MongoDB与Java集成
- 二十一、MongoDB与Spring Boot集成
- 二十二、MongoDB与Docker部署
- 最佳实践篇
- 二十三、MongoDB常见问题解答
- 二十四、MongoDB最佳实践总结
基础篇
一、MongoDB入门指南(零基础必读)
1.1 MongoDB是什么?
把MongoDB想象成一个超级大的Excel表格本:
- 数据库(Database)就像一个Excel工作簿
- 集合(Collection)就像工作簿中的工作表
- 文档(Document)就像工作表中的一行数据
- 字段(Field)就像表格中的列
与传统MySQL数据库相比:
- MySQL要求表格结构固定(每列的类型必须一致)
- MongoDB更灵活,同一个集合中的文档可以有不同的字段
1.2 为什么选择MongoDB?
-
容易上手
- 数据格式类似JSON,对开发者友好
- 不需要设计复杂的表关系
- 存储格式灵活,想存什么就存什么
-
适合的应用场景
- 存储网站用户数据
- 存储商品评论信息
- 记录系统日志
- 存储游戏数据
1.3 基础操作入门示例
1. 数据库操作
// 创建/切换到"我的数据库"
use mydb// 查看有哪些数据库
show dbs// 删除当前使用的数据库
db.dropDatabase()
2. 集合操作
// 创建"用户信息"集合
db.createCollection("用户信息")// 查看所有集合
show collections// 删除"用户信息"集合
db.用户信息.drop()
3. 实用操作示例
添加用户信息
// 添加一个用户
db.用户信息.insertOne({姓名: "小明",年龄: 18,爱好: ["打游戏", "看电影"],联系方式: {手机: "13812345678",邮箱: "xiaoming@example.com"}
})
查询用户信息
// 查找所有用户
db.用户信息.find()// 查找叫"小明"的用户
db.用户信息.find({姓名: "小明"})// 查找18岁的用户
db.用户信息.find({年龄: 18})// 查找大于18岁的用户
db.用户信息.find({年龄: {$gt: 18}})
1.4 新手常见问题解决
1. 数据重复问题
// 设置用户名不能重复
db.users.createIndex({用户名: 1}, {unique: true})// 检查用户名是否存在
const userExists = db.users.findOne({用户名: "xiaoming"})
if (!userExists) {// 可以注册
}
2. 查询速度慢问题
// 为常用查询字段创建索引
db.users.createIndex({年龄: 1})
db.users.createIndex({注册时间: 1})// 只返回需要的字段
db.users.find({年龄: {$gt: 18}},{用户名: 1, 年龄: 1, _id: 0}
)
1.5 新手使用建议
-
命名建议
- 数据库名用小写字母
- 集合名用有意义的名字(如users、products)
- 字段名用简单易懂的名字
-
数据组织建议
- 相关的数据尽量放在一起
- 避免过深的数据嵌套
- 数组中不要存太多数据
-
查询建议
- 常用查询字段要加索引
- 查询时只获取需要的字段
- 避免一次查询太多数据
-
实用技巧
- 使用复合查询减少查询次数
- 使用批量操作提高效率
- 定期备份重要数据
二、MongoDB简介
2.1 什么是MongoDB?
MongoDB是一个开源的文档型数据库,具有以下特点:
- 高性能、高可用性、易扩展
- 支持动态查询
- 支持索引
- 支持复制和分片
- 支持多种编程语言
2.2 基本概念
-
数据库(Database)
- MongoDB中的数据库是一个集合的容器
- 每个数据库都有独立的权限控制
-
集合(Collection)
- 类似于关系型数据库中的表
- 不需要预先定义结构
- 可以包含不同结构的文档
-
文档(Document)
- 类似于关系型数据库中的行
- 使用BSON格式(JSON的二进制形式)
- 可以包含不同类型的字段
-
字段(Field)
- 文档中的键值对
- 支持多种数据类型
- 可以嵌套和数组
三、MongoDB安装与配置
3.1 安装MongoDB
# Windows安装
# 1. 下载MongoDB安装包
# 2. 运行安装程序
# 3. 配置环境变量# Linux安装
sudo apt-get update
sudo apt-get install -y mongodb# Mac安装
brew tap mongodb/brew
brew install mongodb-community
3.2 启动MongoDB
# Windows启动
net start MongoDB# Linux启动
sudo systemctl start mongodb# Mac启动
brew services start mongodb-community
3.3 连接MongoDB
# 命令行连接
mongosh# 指定主机和端口连接
mongosh --host localhost --port 27017# 使用用户名密码连接
mongosh --username admin --password password
四、MongoDB基本操作
4.1 数据库操作
// 创建/切换数据库
use mydb// 查看所有数据库
show dbs// 删除当前数据库
db.dropDatabase()// 查看当前数据库
db
4.2 集合操作
// 创建集合
db.createCollection("users")// 查看所有集合
show collections// 删除集合
db.users.drop()// 查看集合统计信息
db.users.stats()
4.3 文档操作
// 插入单个文档
db.users.insertOne({name: "张三",age: 25,email: "zhangsan@example.com",hobbies: ["读书", "运动"],address: {city: "北京",street: "朝阳区"}
})// 插入多个文档
db.users.insertMany([{name: "李四",age: 30,email: "lisi@example.com"},{name: "王五",age: 28,email: "wangwu@example.com"}
])// 查询文档
db.users.find()// 条件查询
db.users.find({ age: { $gt: 25 } })// 更新文档
db.users.updateOne({ name: "张三" },{ $set: { age: 26 } }
)// 删除文档
db.users.deleteOne({ name: "张三" })
五、MongoDB查询操作
5.1 基础查询
// 查询所有文档
db.users.find()// 条件查询
db.users.find({ age: 25 })// 比较操作符
db.users.find({ age: { $gt: 25 } }) // 大于
db.users.find({ age: { $lt: 25 } }) // 小于
db.users.find({ age: { $gte: 25 } }) // 大于等于
db.users.find({ age: { $lte: 25 } }) // 小于等于
db.users.find({ age: { $ne: 25 } }) // 不等于// 逻辑操作符
db.users.find({ $or: [{ age: 25 }, { age: 30 }] }) // OR
db.users.find({ $and: [{ age: 25 }, { name: "张三" }] }) // AND
db.users.find({ age: { $not: { $gt: 25 } } }) // NOT// 限制返回字段
db.users.find({}, { name: 1, age: 1, _id: 0 })// 排序
db.users.find().sort({ age: 1 }) // 升序
db.users.find().sort({ age: -1 }) // 降序// 分页
db.users.find().skip(10).limit(5)
5.2 高级查询
// 正则表达式查询
db.users.find({ name: /^张/ })// 数组查询
db.users.find({ hobbies: "读书" })
db.users.find({ hobbies: { $all: ["读书", "运动"] } })
db.users.find({ hobbies: { $size: 2 } })// 嵌套文档查询
db.users.find({ "address.city": "北京" })// 聚合查询
db.users.aggregate([{ $group: { _id: "$age", count: { $sum: 1 } } },{ $sort: { count: -1 } }
])
进阶篇
六、MongoDB索引
6.1 索引操作
// 创建索引
db.users.createIndex({ email: 1 })// 创建唯一索引
db.users.createIndex({ email: 1 }, { unique: true })// 创建复合索引
db.users.createIndex({ name: 1, age: -1 })// 查看索引
db.users.getIndexes()// 删除索引
db.users.dropIndex({ email: 1 })
6.2 索引类型
- 单字段索引
- 复合索引
- 多键索引
- 文本索引
- 地理空间索引
- 哈希索引
七、MongoDB聚合操作
7.1 聚合管道
// 基本聚合
db.users.aggregate([{ $match: { age: { $gt: 25 } } },{ $group: { _id: "$age", count: { $sum: 1 } } },{ $sort: { count: -1 } }
])// 复杂聚合
db.orders.aggregate([{ $match: { status: "completed" } },{ $group: {_id: "$customer_id",total: { $sum: "$amount" },count: { $sum: 1 }}},{ $lookup: {from: "customers",localField: "_id",foreignField: "_id",as: "customer"}},{ $unwind: "$customer" },{ $project: {customer_name: "$customer.name",total: 1,count: 1}}
])
7.2 聚合操作符
- $match:过滤文档
- $group:分组
- $sort:排序
- $limit:限制
- $skip:跳过
- $project:投影
- $lookup:关联查询
- $unwind:展开数组
八、MongoDB数据模型
8.1 文档模型
// 嵌入式文档
{_id: ObjectId("..."),name: "张三",orders: [{order_id: "001",amount: 100,items: [{ product: "手机", quantity: 1 },{ product: "耳机", quantity: 2 }]}]
}// 引用式文档
{_id: ObjectId("..."),name: "张三",order_ids: [ObjectId("..."),ObjectId("...")]
}
8.2 数据关系
- 一对一关系
- 一对多关系
- 多对多关系
九、MongoDB安全
9.1 用户管理
// 创建用户
db.createUser({user: "admin",pwd: "password",roles: ["userAdminAnyDatabase"]
})// 修改用户
db.updateUser("admin", {roles: ["userAdminAnyDatabase", "readWriteAnyDatabase"]
})// 删除用户
db.dropUser("admin")
9.2 访问控制
// 启用认证
security:authorization: enabled// 设置访问权限
db.grantRolesToUser("user", ["readWrite"])
十、MongoDB备份恢复
10.1 备份操作
# 备份整个数据库
mongodump --db mydb --out /backup# 备份特定集合
mongodump --db mydb --collection users --out /backup# 压缩备份
mongodump --db mydb --gzip --archive=/backup/backup.gz
10.2 恢复操作
# 恢复整个数据库
mongorestore --db mydb /backup/mydb# 恢复特定集合
mongorestore --db mydb --collection users /backup/mydb/users.bson# 恢复压缩备份
mongorestore --gzip --archive=/backup/backup.gz
十一、MongoDB性能优化
11.1 查询优化
- 使用索引
- 限制返回字段
- 使用投影
- 使用分页
- 避免使用正则表达式
11.2 索引优化
- 创建合适的索引
- 避免过多索引
- 使用复合索引
- 定期维护索引
11.3 配置优化
# mongod.conf
storage:wiredTiger:engineConfig:cacheSizeGB: 4collectionConfig:blockCompressor: snappyoperationProfiling:mode: slowOpslowOpThresholdMs: 100replication:oplogSizeMB: 10240
十二、MongoDB高级特性
12.1 Change Streams
// 监听集合变化
const changeStream = db.collection('users').watch();
changeStream.on('change', (change) => {console.log('检测到变化:', change);
});// 使用管道过滤器
const pipeline = [{ $match: { 'operationType': 'insert' } }
];
const filteredStream = db.collection('users').watch(pipeline);
12.2 事务处理
// 开启事务
const session = db.getMongo().startSession();
session.startTransaction();try {// 转账操作示例db.accounts.updateOne({ userId: "user1" },{ $inc: { balance: -100 } },{ session });db.accounts.updateOne({ userId: "user2" },{ $inc: { balance: 100 } },{ session });await session.commitTransaction();
} catch (error) {await session.abortTransaction();throw error;
} finally {session.endSession();
}
12.3 GridFS文件存储
// 存储大文件
const bucket = new GridFSBucket(db);
fs.createReadStream('video.mp4').pipe(bucket.openUploadStream('video.mp4'));// 读取文件
bucket.openDownloadStreamByName('video.mp4').pipe(fs.createWriteStream('downloaded-video.mp4'));
十三、MongoDB复制集
13.1 复制集配置
# mongod.conf
replication:replSetName: "myReplicaSet"
// 初始化复制集
rs.initiate({_id: "myReplicaSet",members: [{ _id: 0, host: "mongodb1:27017" },{ _id: 1, host: "mongodb2:27017" },{ _id: 2, host: "mongodb3:27017" }]
});// 查看复制集状态
rs.status();// 添加节点
rs.add("mongodb4:27017");// 移除节点
rs.remove("mongodb4:27017");
13.2 复制集运维
// 主节点降级
rs.stepDown();// 设置优先级
cfg = rs.conf();
cfg.members[0].priority = 2;
rs.reconfig(cfg);// 设置隐藏节点
cfg.members[2].hidden = true;
cfg.members[2].priority = 0;
rs.reconfig(cfg);
十四、MongoDB分片集群
14.1 分片集群架构
- Config Server(配置服务器)
- Shard Server(分片服务器)
- Mongos Router(路由服务器)
14.2 分片配置
// 启用分片
sh.enableSharding("mydb");// 对集合进行分片
sh.shardCollection("mydb.users", { userId: "hashed" });// 范围分片
sh.shardCollection("mydb.orders", { orderDate: 1 });// 复合分片键
sh.shardCollection("mydb.products", { category: 1, price: 1 });
应用篇
十五、MongoDB性能诊断
15.1 查询分析
// 执行计划分析
db.users.find({ age: { $gt: 25 } }).explain("executionStats");// 慢查询分析
db.setProfilingLevel(1, { slowms: 100 });
db.system.profile.find().sort({ ts: -1 });// 查询统计
db.users.aggregate([{ $indexStats: {} }
]);
15.2 性能监控
// 服务器状态
db.serverStatus();// 数据库统计
db.stats();// 集合统计
db.users.stats();// 连接情况
db.currentOp();
十六、MongoDB数据迁移
16.1 数据导出
# 导出JSON格式
mongoexport --db mydb --collection users --out users.json# 导出CSV格式
mongoexport --db mydb --collection users --type=csv --fields name,age,email --out users.csv# 条件导出
mongoexport --db mydb --collection users --query '{"age":{"$gt":25}}' --out users_filtered.json
16.2 数据导入
# 导入JSON
mongoimport --db mydb --collection users --file users.json# 导入CSV
mongoimport --db mydb --collection users --type csv --headerline --file users.csv# 导入时进行转换
mongoimport --db mydb --collection users --file users.json --transform 'this.age = Number(this.age)'
十七、MongoDB应用开发最佳实践
17.1 数据建模
// 反范式设计示例
{_id: ObjectId("..."),orderId: "ORD001",customer: {name: "张三",email: "zhangsan@example.com",address: "北京市朝阳区"},items: [{productId: "P001",name: "iPhone",price: 6999,quantity: 1}],totalAmount: 6999,status: "completed"
}
17.2 查询优化技巧
// 使用覆盖索引
db.users.find({ age: { $gt: 25 } },{ _id: 0, name: 1, age: 1 }
).hint({ age: 1, name: 1 });// 使用投影减少网络传输
db.users.find({ },{ name: 1, age: 1, _id: 0 }
);// 批量操作
db.users.bulkWrite([{ insertOne: { document: { name: "张三", age: 25 } } },{ updateOne: { filter: { name: "李四" },update: { $set: { age: 26 } }} },{ deleteOne: { filter: { name: "王五" } } }
]);
17.3 错误处理
try {// 插入唯一索引冲突处理await db.users.insertOne({email: "existing@example.com",name: "张三"});
} catch (error) {if (error.code === 11000) {console.log('邮箱已存在');} else {throw error;}
}
十八、MongoDB运维管理
18.1 日志管理
# mongod.conf
systemLog:destination: filepath: "/var/log/mongodb/mongod.log"logAppend: truelogRotate: rename
18.2 监控告警
// 设置告警阈值
db.createCollection("alerts");
db.alerts.createIndex({ "timestamp": 1 }, { expireAfterSeconds: 86400 });// 监控连接数
const connections = db.serverStatus().connections;
if (connections.current > connections.available * 0.8) {db.alerts.insertOne({type: "connection_warning",message: "连接数超过80%",timestamp: new Date()});
}
18.3 容量规划
- 评估数据增长率
- 监控磁盘使用情况
- 规划扩容时机
- 制定备份策略
十九、MongoDB常见应用场景示例
19.1 用户管理系统
// 用户注册
db.users.insertOne({用户名: "xiaoming",密码: "123456", // 实际应用中要加密注册时间: new Date(),最后登录: new Date(),状态: "正常"
})// 用户登录验证
db.users.findOne({用户名: "xiaoming",密码: "123456"
})// 更新登录时间
db.users.updateOne({用户名: "xiaoming"},{$set: {最后登录: new Date()}}
)
19.2 商品评论系统
// 添加评论
db.comments.insertOne({商品ID: "prod123",用户名: "xiaoming",评分: 5,内容: "很好用!",评论时间: new Date(),点赞数: 0
})// 查看商品评论
db.comments.find({商品ID: "prod123"})// 给评论点赞
db.comments.updateOne({_id: "评论ID"},{$inc: {点赞数: 1}} // $inc表示增加
)
19.3 内容管理系统
// 创建文章
db.articles.insertOne({标题: "MongoDB入门指南",作者: "xiaoming",内容: "MongoDB是一个文档型数据库...",标签: ["数据库", "NoSQL", "MongoDB"],创建时间: new Date(),更新时间: new Date(),阅读量: 0,点赞数: 0
})// 更新文章
db.articles.updateOne({标题: "MongoDB入门指南"},{$set: {更新时间: new Date()},$inc: {阅读量: 1}}
)// 按标签查询文章
db.articles.find({标签: "MongoDB"})
19.4 日志系统
// 记录系统日志
db.logs.insertOne({级别: "ERROR",模块: "用户认证",消息: "用户登录失败",详情: "密码错误",时间: new Date(),用户ID: "user123",IP地址: "192.168.1.1"
})// 查询错误日志
db.logs.find({级别: "ERROR"})// 按时间范围查询
db.logs.find({时间: {$gte: new Date(new Date().setDate(new Date().getDate() - 7)),$lte: new Date()}
})
二十、MongoDB与Java集成
20.1 MongoDB Java驱动
// 添加MongoDB Java驱动依赖
// Maven
<dependency><groupId>org.mongodb</groupId><artifactId>mongodb-driver-sync</artifactId><version>4.11.1</version>
</dependency>// Gradle
implementation 'org.mongodb:mongodb-driver-sync:4.11.1'
20.2 连接MongoDB
// 创建MongoDB客户端
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");// 获取数据库
MongoDatabase database = mongoClient.getDatabase("mydb");// 获取集合
MongoCollection<Document> collection = database.getCollection("users");// 关闭连接
mongoClient.close();
20.3 基本操作示例
// 插入文档
Document document = new Document("name", "张三").append("age", 25).append("email", "zhangsan@example.com");
collection.insertOne(document);// 查询文档
Document query = new Document("name", "张三");
Document result = collection.find(query).first();
System.out.println(result.toJson());// 更新文档
Document updateQuery = new Document("name", "张三");
Document update = new Document("$set", new Document("age", 26));
collection.updateOne(updateQuery, update);// 删除文档
Document deleteQuery = new Document("name", "张三");
collection.deleteOne(deleteQuery);
20.4 使用MongoDB Java驱动的高级功能
// 批量操作
List<WriteModel<Document>> writes = new ArrayList<>();
writes.add(new InsertOneModel<>(new Document("name", "李四").append("age", 30)));
writes.add(new UpdateOneModel<>(new Document("name", "王五"),new Document("$set", new Document("age", 28))
));
writes.add(new DeleteOneModel<>(new Document("name", "赵六")));BulkWriteResult bulkWriteResult = collection.bulkWrite(writes);
System.out.println("插入: " + bulkWriteResult.getInsertedCount());
System.out.println("更新: " + bulkWriteResult.getModifiedCount());
System.out.println("删除: " + bulkWriteResult.getDeletedCount());// 聚合操作
List<Document> pipeline = Arrays.asList(new Document("$match", new Document("age", new Document("$gt", 25))),new Document("$group", new Document("_id", "$age").append("count", new Document("$sum", 1))),new Document("$sort", new Document("count", -1))
);MongoCursor<Document> cursor = collection.aggregate(pipeline).iterator();
while (cursor.hasNext()) {System.out.println(cursor.next().toJson());
}
二十一、MongoDB与Spring Boot集成
21.1 添加Spring Data MongoDB依赖
<!-- Maven -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency><!-- Gradle -->
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
21.2 配置MongoDB连接
# application.yml
spring:data:mongodb:uri: mongodb://localhost:27017/mydb# 或者使用以下配置# host: localhost# port: 27017# database: mydb# username: admin# password: password
21.3 创建实体类
@Document(collection = "users")
public class User {@Idprivate String id;private String name;private int age;private String email;private List<String> hobbies;private Address address;// 构造函数、getter和setter方法// 内部类public static class Address {private String city;private String street;// 构造函数、getter和setter方法}
}
21.4 创建Repository接口
@Repository
public interface UserRepository extends MongoRepository<User, String> {// 自定义查询方法List<User> findByAgeGreaterThan(int age);List<User> findByNameStartingWith(String prefix);Optional<User> findByEmail(String email);// 使用@Query注解自定义查询@Query("{ 'age' : { $gt : ?0, $lt : ?1 } }")List<User> findByAgeBetween(int minAge, int maxAge);
}
21.5 使用MongoDB Template
@Service
public class UserService {@Autowiredprivate MongoTemplate mongoTemplate;public List<User> findUsersByAge(int age) {Query query = new Query(Criteria.where("age").gt(age));return mongoTemplate.find(query, User.class);}public void updateUserAge(String id, int newAge) {Query query = new Query(Criteria.where("id").is(id));Update update = new Update().set("age", newAge);mongoTemplate.updateFirst(query, update, User.class);}public List<User> aggregateUsersByAge() {Aggregation aggregation = Aggregation.newAggregation(Aggregation.match(Criteria.where("age").gt(25)),Aggregation.group("age").count().as("count"),Aggregation.sort(Sort.Direction.DESC, "count"));AggregationResults<User> results = mongoTemplate.aggregate(aggregation, "users", User.class);return results.getMappedResults();}
}
二十二、MongoDB与Docker部署
22.1 使用Docker运行MongoDB
# 拉取MongoDB镜像
docker pull mongo:latest# 运行MongoDB容器
docker run -d --name mongodb -p 27017:27017 mongo:latest# 运行MongoDB容器(带数据持久化)
docker run -d --name mongodb -p 27017:27017 -v /data/mongodb:/data/db mongo:latest# 运行MongoDB容器(带认证)
docker run -d --name mongodb -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=password mongo:latest
22.2 使用Docker Compose部署MongoDB
# docker-compose.yml
version: '3'
services:mongodb:image: mongo:latestcontainer_name: mongodbports:- "27017:27017"volumes:- ./data:/data/dbenvironment:- MONGO_INITDB_ROOT_USERNAME=admin- MONGO_INITDB_ROOT_PASSWORD=passwordnetworks:- mongo-networkmongo-express:image: mongo-express:latestcontainer_name: mongo-expressports:- "8081:8081"environment:- ME_CONFIG_MONGODB_ADMINUSERNAME=admin- ME_CONFIG_MONGODB_ADMINPASSWORD=password- ME_CONFIG_MONGODB_URL=mongodb://admin:password@mongodb:27017/depends_on:- mongodbnetworks:- mongo-networknetworks:mongo-network:driver: bridge
22.3 使用Docker部署MongoDB复制集
# docker-compose-replica.yml
version: '3'
services:mongodb1:image: mongo:latestcontainer_name: mongodb1command: mongod --replSet rs0 --bind_ip_allports:- "27017:27017"volumes:- ./data1:/data/dbnetworks:- mongo-networkmongodb2:image: mongo:latestcontainer_name: mongodb2command: mongod --replSet rs0 --bind_ip_allports:- "27018:27017"volumes:- ./data2:/data/dbnetworks:- mongo-networkmongodb3:image: mongo:latestcontainer_name: mongodb3command: mongod --replSet rs0 --bind_ip_allports:- "27019:27017"volumes:- ./data3:/data/dbnetworks:- mongo-networknetworks:mongo-network:driver: bridge
# 初始化复制集
docker exec -it mongodb1 mongosh --eval "rs.initiate({_id: 'rs0',members: [{_id: 0, host: 'mongodb1:27017'},{_id: 1, host: 'mongodb2:27017'},{_id: 2, host: 'mongodb3:27017'}]
})"
最佳实践篇
二十三、MongoDB常见问题解答
23.1 连接问题
问题: 无法连接到MongoDB服务器
解决方案:
- 检查MongoDB服务是否正在运行
- 检查防火墙设置,确保端口27017开放
- 检查MongoDB配置文件中的bindIp设置
- 如果使用认证,确保用户名和密码正确
23.2 性能问题
问题: MongoDB查询速度慢
解决方案:
- 为常用查询字段创建索引
- 使用explain()分析查询执行计划
- 优化查询,只返回需要的字段
- 检查服务器资源使用情况(CPU、内存、磁盘I/O)
- 考虑增加服务器资源或使用分片集群
23.3 数据一致性问题
问题: 在复制集中出现数据不一致
解决方案:
- 检查复制集状态:
rs.status()
- 检查主节点和从节点的数据差异
- 如果从节点落后太多,考虑重新同步
- 确保网络连接稳定,避免网络分区
23.4 内存问题
问题: MongoDB占用过多内存
解决方案:
- 调整WiredTiger缓存大小
- 监控内存使用情况
- 考虑增加服务器内存
- 优化查询和索引,减少内存使用
23.5 磁盘空间问题
问题: MongoDB磁盘空间不足
解决方案:
- 清理不需要的数据
- 压缩集合:
db.runCommand({compact: "collection_name"})
- 增加磁盘空间
- 考虑使用分片集群分散数据
二十四、MongoDB最佳实践总结
24.1 数据建模最佳实践
-
嵌入vs引用
- 一对少关系:使用嵌入
- 一对多关系:根据查询模式决定
- 多对多关系:通常使用引用
-
文档大小
- 保持文档大小在16MB以下
- 避免过深的嵌套(不超过3-4层)
- 避免过大的数组
-
字段命名
- 使用简短但有意义的字段名
- 保持命名风格一致
- 避免使用特殊字符
24.2 查询优化最佳实践
-
索引策略
- 为所有查询创建适当的索引
- 避免过多索引(每个集合不超过64个)
- 使用复合索引支持多字段查询
- 考虑索引顺序(等值查询字段放在前面)
-
查询模式
- 使用覆盖索引减少内存使用
- 使用投影只返回需要的字段
- 使用批量操作代替多次单文档操作
- 避免使用正则表达式进行前缀查询
24.3 运维最佳实践
-
监控
- 监控服务器资源使用情况
- 监控查询性能
- 监控复制集状态
- 设置告警阈值
-
备份
- 定期备份数据
- 测试恢复流程
- 保存备份记录
- 考虑使用云服务提供商的备份功能
-
安全
- 启用认证
- 限制网络访问
- 定期更新密码
- 使用TLS/SSL加密传输
-
扩展
- 垂直扩展:增加服务器资源
- 水平扩展:使用分片集群
- 根据数据增长和访问模式规划扩展策略
24.4 应用开发最佳实践
-
连接管理
- 使用连接池
- 正确关闭连接
- 处理连接异常
-
错误处理
- 捕获并处理MongoDB异常
- 实现重试机制
- 记录错误日志
-
事务使用
- 只在必要时使用事务
- 保持事务简短
- 考虑使用补偿事务代替长时间运行的事务
-
代码组织
- 使用数据访问层封装MongoDB操作
- 使用ORM框架简化开发
- 遵循领域驱动设计原则