MongoDB 完整指南
MongoDB 完整指南
目录
- MongoDB简介
- 核心概念
- 使用技巧
- 重难点解析
- Spring Boot集成
- 最佳实践
MongoDB简介
什么是MongoDB
MongoDB是一个基于分布式文件存储的NoSQL数据库,由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。
主要特点
- 文档导向: 数据以BSON(Binary JSON)格式存储
- 高性能: 支持索引、聚合、分片等特性
- 高可用性: 支持复制集和自动故障转移
- 水平扩展: 支持分片集群,可横向扩展
- 灵活模式: 无需预定义表结构,支持动态字段
适用场景
- 大数据量、高并发的Web应用
- 内容管理系统
- 实时分析系统
- 物联网数据存储
- 日志系统
核心概念
数据库结构
MongoDB实例
├── 数据库(Database)
│ ├── 集合(Collection) - 相当于关系数据库中的表
│ │ ├── 文档(Document) - 相当于关系数据库中的行
│ │ │ ├── 字段(Field) - 相当于关系数据库中的列
│ │ │ └── 值(Value)
│ │ └── 索引(Index)
│ └── 用户(User)
└── 配置(Configuration)
数据类型
- 基本类型: String, Number, Boolean, Date, ObjectId
- 复合类型: Array, Object, Null
- 特殊类型: Binary Data, Regular Expression, Timestamp
使用技巧
1. 索引优化
// 创建单字段索引
db.collection.createIndex({ "field": 1 })// 创建复合索引
db.collection.createIndex({ "field1": 1, "field2": -1 })// 创建文本索引
db.collection.createIndex({ "content": "text" })// 创建地理空间索引
db.collection.createIndex({ "location": "2dsphere" })
2. 聚合管道
// 复杂聚合查询示例
db.orders.aggregate([{ $match: { status: "completed" } },{ $group: { _id: "$customerId", totalAmount: { $sum: "$amount" },orderCount: { $sum: 1 }}},{ $sort: { totalAmount: -1 } },{ $limit: 10 }
])
3. 批量操作
// 批量插入
db.collection.bulkWrite([{ insertOne: { document: { name: "John", age: 30 } } },{ insertOne: { document: { name: "Jane", age: 25 } } },{ updateOne: { filter: { name: "John" }, update: { $set: { age: 31 } } } }
])
4. 数据验证
// 创建集合时定义验证规则
db.createCollection("users", {validator: {$jsonSchema: {required: ["name", "email"],properties: {name: { type: "string", minLength: 2 },email: { type: "string", pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" },age: { type: "number", minimum: 0, maximum: 150 }}}}
})
重难点解析
1. 事务处理
// MongoDB 4.0+ 支持多文档事务
const session = db.getMongo().startSession();
session.startTransaction();try {// 执行多个操作db.accounts.updateOne({ _id: "account1" },{ $inc: { balance: -100 } },{ session });db.accounts.updateOne({ _id: "account2" },{ $inc: { balance: 100 } },{ session });session.commitTransaction();
} catch (error) {session.abortTransaction();throw error;
} finally {session.endSession();
}
2. 分片策略
// 启用分片
sh.enableSharding("database")// 对集合进行分片
sh.shardCollection("database.collection", { "shardKey": 1 })// 分片键选择原则
// - 基数高(唯一值多)
// - 写分布均匀
// - 支持单调递增
3. 复制集配置
// 复制集配置示例
config = {_id: "rs0",members: [{ _id: 0, host: "mongodb0.example.net:27017" },{ _id: 1, host: "mongodb1.example.net:27017" },{ _id: 2, host: "mongodb2.example.net:27017" }]
}rs.initiate(config)
4. 性能优化
// 使用投影减少数据传输
db.collection.find({}, { name: 1, email: 1, _id: 0 })// 使用hint强制使用特定索引
db.collection.find({ field: "value" }).hint({ field: 1 })// 使用explain分析查询性能
db.collection.find({ field: "value" }).explain("executionStats")
Spring Boot集成
1. 依赖配置
<!-- 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'
2. 配置文件
# application.yml
spring:data:mongodb:host: localhostport: 27017database: mydbusername: adminpassword: passwordauthentication-database: admin# 连接池配置max-connection-pool-size: 100min-connection-pool-size: 5max-connection-idle-time: 30000# 复制集配置# uri: mongodb://user:pass@host1:port1,host2:port2/database?replicaSet=rs0
3. 实体类定义
@Document(collection = "users")
public class User {@Idprivate String id;@Indexed(unique = true)private String email;private String name;private int age;@CreatedDateprivate LocalDateTime createdAt;@LastModifiedDateprivate LocalDateTime updatedAt;// 构造函数、getter、setter
}
4. Repository接口
@Repository
public interface UserRepository extends MongoRepository<User, String> {// 自定义查询方法List<User> findByName(String name);List<User> findByAgeGreaterThan(int age);@Query("{ 'age' : { $gte : ?0, $lte : ?1 } }")List<User> findByAgeBetween(int minAge, int maxAge);// 使用正则表达式List<User> findByNameRegex(String regex);// 分页查询Page<User> findByAge(int age, Pageable pageable);
}
5. 服务层实现
@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Autowiredprivate MongoTemplate mongoTemplate;// 基本CRUD操作public User createUser(User user) {return userRepository.save(user);}public User findById(String id) {return userRepository.findById(id).orElseThrow(() -> new UserNotFoundException("User not found"));}// 使用MongoTemplate进行复杂查询public List<User> findUsersByComplexCriteria(String name, int minAge, String city) {Criteria criteria = new Criteria();if (name != null) {criteria = criteria.and("name").regex(name, "i");}if (minAge > 0) {criteria = criteria.and("age").gte(minAge);}if (city != null) {criteria = criteria.and("address.city").is(city);}Query query = new Query(criteria);return mongoTemplate.find(query, User.class);}// 聚合查询public List<AgeGroup> getUsersByAgeGroup() {Aggregation aggregation = Aggregation.newAggregation(Aggregation.group("age").count().as("count").avg("age").as("averageAge"),Aggregation.sort(Sort.Direction.ASC, "_id"));return mongoTemplate.aggregate(aggregation, "users", AgeGroup.class).getMappedResults();}// 批量操作@Transactionalpublic void updateUsersAge(String name, int newAge) {Query query = new Query(Criteria.where("name").is(name));Update update = new Update().set("age", newAge);mongoTemplate.updateMulti(query, update, User.class);}
}
6. 控制器层
@RestController
@RequestMapping("/api/users")
public class UserController {@Autowiredprivate UserService userService;@PostMappingpublic ResponseEntity<User> createUser(@RequestBody User user) {User createdUser = userService.createUser(user);return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);}@GetMapping("/{id}")public ResponseEntity<User> getUserById(@PathVariable String id) {User user = userService.findById(id);return ResponseEntity.ok(user);}@GetMapping("/search")public ResponseEntity<List<User>> searchUsers(@RequestParam(required = false) String name,@RequestParam(required = false) Integer minAge,@RequestParam(required = false) String city) {List<User> users = userService.findUsersByComplexCriteria(name, minAge, city);return ResponseEntity.ok(users);}@GetMapping("/age-groups")public ResponseEntity<List<AgeGroup>> getAgeGroups() {List<AgeGroup> ageGroups = userService.getUsersByAgeGroup();return ResponseEntity.ok(ageGroups);}
}
7. 配置类
@Configuration
@EnableMongoRepositories(basePackages = "com.example.repository")
public class MongoConfig extends AbstractMongoClientConfiguration {@Value("${spring.data.mongodb.database}")private String databaseName;@Overrideprotected String getDatabaseName() {return databaseName;}@Beanpublic MongoTemplate mongoTemplate() throws Exception {return new MongoTemplate(mongoClient(), getDatabaseName());}// 自定义转换器@Beanpublic MongoCustomConversions customConversions() {List<Converter<?, ?>> converters = new ArrayList<>();converters.add(new LocalDateTimeToDateConverter());converters.add(new DateToLocalDateTimeConverter());return new MongoCustomConversions(converters);}
}
最佳实践
1. 数据建模
- 嵌入文档: 适合一对少关系,数据不经常变化
- 引用文档: 适合一对多关系,数据经常变化
- 混合模式: 根据查询模式选择最优方案
2. 索引策略
- 为常用查询字段创建索引
- 避免过多索引(影响写入性能)
- 使用复合索引优化多字段查询
- 定期分析索引使用情况
3. 性能优化
- 使用投影减少数据传输
- 合理使用分页查询
- 避免深度嵌套查询
- 使用聚合管道替代应用层处理
4. 安全配置
- 启用身份验证
- 使用TLS/SSL加密
- 限制网络访问
- 定期备份数据
5. 监控和维护
- 监控连接数和性能指标
- 定期清理无用索引
- 监控磁盘空间使用
- 设置告警机制
总结
MongoDB作为NoSQL数据库的代表,具有灵活的数据模型、高性能和良好的扩展性。通过合理的数据建模、索引优化和Spring Boot集成,可以构建高效、可扩展的应用程序。
关键要点:
- 理解MongoDB的文档模型和查询语言
- 掌握索引和聚合管道的使用
- 合理设计数据模型和查询策略
- 正确配置Spring Boot集成
- 遵循最佳实践确保性能和安全性
通过本指南的学习,您应该能够熟练使用MongoDB并成功集成到Spring Boot项目中。