在MongoDB中,MongoRepository、原生查询(Native Query)、聚合框架(Aggregation Framework)是三种不同的查询和数据处理方式,它们适用于不同的场景和需求。
- MongoRepository:
- 场景: 当你的查询需求简单,可以通过方法名命名规则进行快速的CRUD操作时,使用MongoRepository是一个不错的选择。
- 优点: 简单易用,无需编写原生的查询语句;Spring Data MongoDB 提供的MongoRepository接口已经实现了很多常见的查询方法。
- 缺点: 适用于基本的CRUD操作和一些简单查询,但对于复杂的聚合和定制查询,可能不够灵活。
public interface UserRepository extends MongoRepository<User, String> {
List<User> findByFirstName(String firstName);
List<User> findByLastName(String lastName);
}
List<Thing> things = thingRepository.findByDeletedAtIsNull();
//复杂查询也是支持的,之前写了巨长的多条件查询也是可以一句代替的
//根据thingId,查询最新的一条数据
public interface ThingDataRepository extends MongoRepository<ThingData, String> {
ThingData findFirstByThingIdOrderByTimestampDesc(String thingId);
}
//如果查询条件更多更复杂多样,则只能使用聚合查询方法,更高效
2024.1.29加更:
Thing findByThirdPlatformConfigThirdDeviceIdAndDeletedAtIsNull(String thirdDeviceId);
//这样看起来太长,可以通过注解合理的简化成下面的格式
@Query("{'thirdPlatformConfig.thirdDeviceId': ?0, 'deletedAt': null}")
Thing findByThirdDeviceId(String thirdDeviceId);
原生查询(Native Query):
- 场景: 当需要执行一些特定的、复杂的 MongoDB 查询语句时,使用原生查询可以提供更大的灵活性。
- 优点: 可以直接使用 MongoDB 的查询语法,适用于一些高级查询和特殊需求。
- 缺点: 需要手动编写 MongoDB 查询语句,可能不够易读和易维护。
原生:
Query query = new Query();
query.addCriteria(Criteria.where("deletedAt").is(null));
List<Thing> things = mongoTemplate.find(query, Thing.class);
聚合框架(Aggregation Framework):
- 场景: 当需要进行复杂的数据处理和分析,或者需要对多个文档进行聚合操作时,使用聚合框架是一个强大的选择。
- 优点: 能够处理复杂的数据聚合操作,支持多个阶段的数据处理流程,提供更高级的数据分析能力。
- 缺点: 编写聚合管道可能较为繁琐,对于简单查询而言可能过于复杂。
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(Criteria.where("age").gte(25)),
Aggregation.group("city").count().as("userCount"),
Aggregation.sort(Sort.Direction.DESC, "userCount")
);
AggregationResults<CityStats> results = mongoTemplate.aggregate(aggregation, "user", CityStats.class);
List<CityStats> cityStatsList = results.getMappedResults();
//---------------案例--------------------/
// 创建一个空的关键字条件
Criteria keywordCriteria = new Criteria();
for (ThingModelDTO.PropertyDTO propSpecDTO : propertiesSpec) {
String propIdentifier = propSpecDTO.getIdentifier();
// 第一步:构建基本查询条件,根据thingId和属性标识符查询
Criteria baseCriteria = Criteria.where("thingId").is(thingId)
.and("property.identifier").is(propIdentifier);
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(baseCriteria),
// 如果有关键字,再执行模糊匹配
Aggregation.match(keywordCriteria),
Aggregation.sort(Sort.by(Sort.Order.desc("property.timestamp"))),
Aggregation.group("property.identifier")
.first("property.identifier").as("identifier")
.first("property.value").as("value")
.first("property.timestamp").as("timestamp")
);
try {
AggregationResults<ThingData.PropertyData> aggregationResults = mongoTemplate.aggregate(
aggregation, "thingData", ThingData.PropertyData.class);
List<ThingData.PropertyData> matchingData = aggregationResults.getMappedResults();
- 使用MongoRepository进行简单的CRUD操作和基本查询。
- 使用原生查询处理一些特殊需求,无法通过MongoRepository提供的方法满足的情况。
- 使用聚合框架处理复杂的数据聚合和分析任务。
综合考虑业务需求和查询复杂度,可以根据具体场景选择合适的查询方式,甚至在一个应用中同时使用多种方式。