如何通过Spring Data MongoDB聚合查询获取各projectId的统计数据
解决方案:获取MongoDB聚合查询中每个projectId的统计值
1. 定义聚合结果映射类
Spring Data MongoDB需要将聚合结果映射到Java对象,创建一个DTO类来接收分组后的统计数据,注意projectId为long类型,totalAmount对应MongoDB的decimal类型,用Java的BigDecimal接收:
import java.math.BigDecimal; public class ProjectStats { private long projectId; private long totalCount; private BigDecimal totalAmount; // 必须提供全参构造方法,Spring Data MongoDB会用它映射结果 public ProjectStats(long projectId, long totalCount, BigDecimal totalAmount) { this.projectId = projectId; this.totalCount = totalCount; this.totalAmount = totalAmount; } // Getter方法 public long getProjectId() { return projectId; } public long getTotalCount() { return totalCount; } public BigDecimal getTotalAmount() { return totalAmount; } }
2. 执行聚合查询并映射结果
通过MongoTemplate执行你定义的聚合操作,指定结果类型为上面的ProjectStats:
// 假设已注入MongoTemplate @Autowired private MongoTemplate mongoTemplate; // 补全原代码中updatedTime的gt/lt参数(示例传入起止时间) Aggregation aggregate = newAggregation( match(Criteria.where("projectId").in(projectIdList) .and("isAvailable").is(false) // 单个值匹配用is比in更高效 .and("status").is("rejected") .and("updatedTime").gt(startTime).lt(endTime)), group("projectId") .count().as("totalCount") .sum(ConvertOperators.Convert.convertValueOf("amount").to("decimal")).as("totalAmount") ); // 执行聚合并映射结果 AggregationResults<ProjectStats> results = mongoTemplate.aggregate(aggregate, "你的集合名称", ProjectStats.class); List<ProjectStats> projectStatsList = results.getMappedResults();
3. 快速获取单个projectId的统计值
如果需要通过projectId快速查找对应数据,可将结果列表转为Map<Long, ProjectStats>:
import java.util.stream.Collectors; Map<Long, ProjectStats> statsMap = projectStatsList.stream() .collect(Collectors.toMap(ProjectStats::getProjectId, stats -> stats)); // 示例:获取指定projectId的统计数据 long targetProjectId = 123L; if (statsMap.containsKey(targetProjectId)) { ProjectStats stats = statsMap.get(targetProjectId); System.out.println("统计数量:" + stats.getTotalCount()); System.out.println("统计金额:" + stats.getTotalAmount()); }
注意事项
- 原代码中
isAvailable.in(false)建议改为isAvailable.is(false),单个值匹配无需用in语法 - 确保
updatedTime的gt/lt参数已正确传入,否则match条件会失效 - 如果集合名称通过实体类
@Document注解指定,可直接传入实体类class替代字符串集合名,比如YourEntity.class
内容的提问来源于stack exchange,提问作者trytocode
相关产品推荐
相关产品推荐

