Spring项目中MongoDB聚合avg查询转Java代码问题
解决Spring Data MongoDB中ProjectionOperation使用$avg的问题
我明白你遇到的困扰了——Spring Data MongoDB的ProjectionOperation确实没有直接提供avg()方法,但这不代表我们不能在投影阶段使用$avg聚合函数,只需要换一种方式手动构建表达式就行。
先看你的原MongoDB查询:
db.test.aggregate([ {$unwind: "$reports"}, {$project: {reports: 1, avg: {$avg: "$reports.linesCount"}}} ])
不过这里有个小细节:unwind之后每个文档只包含单个reports对象,所以$avg计算的其实就是当前文档的linesCount值。如果你的真实需求是计算每个原始文档下所有reports.linesCount的平均值,其实不需要unwind,直接在投影阶段对数组字段用$avg即可;如果确实需要unwind后再计算,下面的代码都能覆盖。
解决方案1:使用andExpression()快速构建投影
这是最简洁的方式,直接通过字符串表达式来定义$avg操作:
import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.ProjectionOperation; import org.springframework.data.mongodb.core.aggregation.UnwindOperation; // 构建unwind操作(如果不需要可以去掉) UnwindOperation unwind = Aggregation.unwind("$reports"); // 构建投影操作,手动添加$avg表达式 ProjectionOperation project = Aggregation.project("reports") .andExpression("avg(reports.linesCount)") // 直接用表达式语法 .as("avg"); // 指定输出字段名 // 组合聚合操作 Aggregation aggregation = Aggregation.newAggregation(unwind, project);
解决方案2:使用AggregationExpression自定义表达式
如果需要更灵活的控制(比如复杂的条件聚合),可以用AggregationExpression手动构建MongoDB的$avg文档:
import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationExpression; import org.springframework.data.mongodb.core.aggregation.ProjectionOperation; import org.springframework.data.mongodb.core.aggregation.UnwindOperation; import org.bson.Document; UnwindOperation unwind = Aggregation.unwind("$reports"); // 自定义$avg表达式 AggregationExpression avgExpr = context -> new Document("$avg", "$reports.linesCount"); ProjectionOperation project = Aggregation.project("reports") .and(avgExpr) .as("avg"); Aggregation aggregation = Aggregation.newAggregation(unwind, project);
补充:如果需求是计算全局平均值
如果你想要的是所有unwind后文档的linesCount的全局平均值,那需要用GroupOperation来实现(这也是你之前注意到的Group支持avg的场景):
import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.GroupOperation; import org.springframework.data.mongodb.core.aggregation.UnwindOperation; UnwindOperation unwind = Aggregation.unwind("$reports"); // 按null分组(全局分组),计算平均值 GroupOperation group = Aggregation.group() .avg("reports.linesCount") .as("avg"); Aggregation aggregation = Aggregation.newAggregation(unwind, group);
这样就能完美匹配你想要的聚合逻辑啦。
内容的提问来源于stack exchange,提问作者Adam Hasan
相关产品推荐
相关产品推荐

