MongoDB 集成
约 807 字大约 3 分钟
布欧-Lewyon
2026-05-16
首页 › Spring Boot › 数据访问 › MongoDB 集成
MongoDB 是主流文档型 NoSQL 数据库,适合灵活 Schema、快速迭代和高写入吞吐的场景。Spring Data MongoDB 提供与 JPA 相似的 Repository 抽象。
起步依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>spring:
data:
mongodb:
uri: mongodb://localhost:27017/mydb
# 或分项配置:
# host: localhost
# port: 27017
# database: mydb
# username: user
# password: ${MONGO_PASSWORD}实体映射
@Document(collection = "users") // 对应 MongoDB 集合
public class User {
@Id
private String id; // MongoDB 使用 String 或 ObjectId
@Field("user_name")
private String userName;
private Integer age;
@Field("created_at")
private LocalDateTime createdAt;
// 嵌套文档
private Address address;
// getter / setter
}
public class Address {
private String city;
private String street;
}Repository
public interface UserRepository extends MongoRepository<User, String> {
// 方法名查询
List<User> findByUserName(String userName);
List<User> findByAgeGreaterThanEqual(Integer age);
// JSON 查询(支持 MongoDB JSON 查询语法)
@Query("{ 'address.city': ?0 }")
List<User> findByCity(String city);
}@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User save(User user) {
if (user.getCreatedAt() == null) {
user.setCreatedAt(LocalDateTime.now());
}
return userRepository.save(user);
}
public List<User> findByAgeRange(int min, int max) {
return userRepository.findByAgeGreaterThanEqual(min);
}
}MongoTemplate(灵活查询)
对于复杂聚合管道(Aggregation Pipeline),使用 MongoTemplate:
@Service
public class ReportService {
private final MongoTemplate mongoTemplate;
public ReportService(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
public List<UserAgeStat> ageStatistics() {
Aggregation agg = Aggregation.newAggregation(
Aggregation.group("age").count().as("count"),
Aggregation.sort(Sort.Direction.DESC, "count"),
Aggregation.limit(10)
);
AggregationResults<UserAgeStat> results = mongoTemplate.aggregate(
agg, "users", UserAgeStat.class);
return results.getMappedResults();
}
}地理空间查询
MongoDB 原生支持地理空间索引(2dsphere),Spring Data MongoDB 封装了 NearQuery:
// 集合需创建 2dsphere 索引
// db.places.createIndex({ location: "2dsphere" })
@Document(collection = "places")
public class Place {
@Id
private String id;
private String name;
@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
private GeoJsonPoint location; // { type: "Point", coordinates: [lng, lat] }
}public interface PlaceRepository extends MongoRepository<Place, String> {
// 附近查询(Spring Data MongoDB 3.x+)
List<Place> findByLocationNear(Point point, Distance distance);
}// 使用 MongoTemplate + NearQuery
NearQuery query = NearQuery.near(116.397, 39.908, Metrics.KILOMETERS)
.maxDistance(5)
.spherical(true);
GeoResults<Place> results = mongoTemplate.geoNear(query, Place.class);MySQL vs MongoDB 选型
| 对比维度 | MySQL(关系型) | MongoDB(文档型) |
|---|---|---|
| Schema | 固定表结构 | 灵活 JSON 文档 |
| 查询 | SQL + JOIN | 类 JSON 查询 + 聚合管道 |
| 事务 | 强 ACID(支持跨表) | 文档级 ACID(4.0+ 支持多文档事务) |
| 索引 | B+ 树 | B+ 树 + 地理空间 + TTL + 文本 |
| 水平扩展 | 分库分表(中间件) | 原生分片(Sharding) |
| 写入性能 | 中等(事务开销) | 高(无 JOIN、无 Schema 校验) |
选型建议:
- 强一致性、复杂关联查询 → MySQL/PostgreSQL
- 灵活 Schema、高写入量、文档为主 → MongoDB
- 混合:核心数据(订单、账户)用关系型,日志/配置/地理数据用 MongoDB
小结
spring-boot-starter-data-mongodb自动配置MongoTemplate和MongoRepository。- Repository 方法名查询、
@QueryJSON 查询、聚合管道三种查询手段覆盖绝大多数场景。 - 地理空间搜索是 MongoDB 的差异化优势——
NearQuery+2dsphere索引。 - 选型:MongoDB 适合 Schema 灵活、高写入、文档型场景;关系型数据库适合强一致性、多表关联。
- 易错:MongoDB 默认没有事务——跨文档操作需要用
@Transactional(需 MongoDB 4.0+ 副本集)。_id字段类型为String时,保存时必须手动赋值,否则 MongoDB 会自动生成ObjectId。嵌套文档的字段名使用@Field指定列名,否则序列化字段名与 Java 属性名一致。 - 思考任务:启动本地 MongoDB,创建一个 User 集合,用
MongoRepository实现按年龄范围查询和按城市聚合统计。
上一节:数据库迁移
下一节:缓存
