如何将MongoDB去重国家信息的聚合查询转为Spring Reactive Mongo实现
正确Spring Reactive MongoDB聚合实现
核心问题说明
你原有代码存在两处不符合需求的问题:
- 错误添加了语法不正确且不匹配需求的match过滤条件
- group阶段逻辑和原生查询不一致,没有按
countryCode+countryName组合字段分组去重
实现代码
场景1:无过滤条件,查询全量去重的国家编码+名称
import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.stereotype.Repository; import reactor.core.publisher.Flux; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; @Repository public class AggregateQueryRepository { private final ReactiveMongoTemplate reactiveMongoTemplate; // 推荐用构造注入替代@Autowired public AggregateQueryRepository(ReactiveMongoTemplate reactiveMongoTemplate) { this.reactiveMongoTemplate = reactiveMongoTemplate; } public Flux<Location> getAllCountryCodeAndCountry() { Aggregation aggregation = newAggregation( // 按countryCode和countryName组合分组,天然实现去重,和原生查询逻辑完全一致 group("countryCode", "countryName"), // 将分组后嵌套在_id内的字段映射为Location实体的对应属性 project() .and("_id.countryCode").as("countryCode") .and("_id.countryName").as("countryName") ); return reactiveMongoTemplate.aggregate(aggregation, "location", Location.class); } }
场景2:支持按传入的countryCode、countryName参数过滤后再去重
import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.stereotype.Repository; import reactor.core.publisher.Flux; import java.util.ArrayList; import java.util.List; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; @Repository public class AggregateQueryRepository { private final ReactiveMongoTemplate reactiveMongoTemplate; public AggregateQueryRepository(ReactiveMongoTemplate reactiveMongoTemplate) { this.reactiveMongoTemplate = reactiveMongoTemplate; } public Flux<Location> getAllCountryCodeAndCountry(String countryCode, String countryName) { List<AggregationOperation> operations = new ArrayList<>(); // 动态拼接过滤条件,参数不为空时才生效 Criteria criteria = new Criteria(); if (countryCode != null) { criteria.and("countryCode").is(countryCode); } if (countryName != null) { criteria.and("countryName").is(countryName); } if (!criteria.getCriteriaObject().isEmpty()) { operations.add(match(criteria)); } // 分组去重 operations.add(group("countryCode", "countryName")); // 字段映射 operations.add(project() .and("_id.countryCode").as("countryCode") .and("_id.countryName").as("countryName")); Aggregation aggregation = newAggregation(operations); return reactiveMongoTemplate.aggregate(aggregation, "location", Location.class); } }
注意事项
请确保你的Location实体类中存在countryCode和countryName两个属性,且有对应的get/set方法,否则字段映射会失败。
内容的提问来源于stack exchange,提问作者Mira Devi
相关产品推荐
相关产品推荐

