Spring Data MongoDB分组投影实现支付类型金额聚合求助
问题描述
现有3条MongoDB示例记录:
{ "_id" : "0cc5c468-2105-11ee-ad68-15d467e62by4d", "storeId" : "3070", "paymentType" : "cash", "total" : {"$numberDecimal": "100"} }, { "_id" : "1111111-2105-11ee-ad68-15d467e62by4d", "storeId" : "3070", "paymentType" : "cash", "total" : {"$numberDecimal": "100"} }, { "_id" : "0cc5c468-2105-11ee-ad68-15d467e62by4d", "storeId" : "3070", "paymentType" : "creditCard", "total" : {"$numberDecimal": "50"} }
期望通过分组投影得到如下格式的输出(最后一列可忽略):
StoreId | Cash Payment | Card Payment | Total Amount Cash + Card 3070 200 50 250
当前编写的GroupOperation会生成现金支付和信用卡支付两条独立记录,不符合预期:
GroupOperation groupingLogic() { return group("storeId", "paymentType") .first("storeId").as("storeId") .first("paymentType").as("paymentType") .sum(TOTAL).as(TOTAL); }
需要正确的Java MongoDB实现代码。
解决方案
正确的做法是仅按storeId分组,使用条件求和分别计算不同支付类型的总额,同时可额外计算总和。以下是实现代码:
import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.GroupOperation; import org.springframework.data.mongodb.core.aggregation.ProjectionOperation; import static org.springframework.data.mongodb.core.aggregation.Aggregation.*; import static org.springframework.data.mongodb.core.aggregation.ConditionalOperators.when; public class StorePaymentAggregation { private static final String STORE_ID = "storeId"; private static final String PAYMENT_TYPE = "paymentType"; private static final String TOTAL = "total"; private static final String CASH_PAYMENT = "Cash Payment"; private static final String CARD_PAYMENT = "Card Payment"; private static final String TOTAL_AMOUNT = "Total Amount Cash + Card"; public GroupOperation groupingLogic() { return group(STORE_ID) // 统计现金支付总额:仅累加paymentType为cash的total值 .sum(when(PAYMENT_TYPE).is("cash").then(TOTAL).otherwise(0)).as(CASH_PAYMENT) // 统计信用卡支付总额:仅累加paymentType为creditCard的total值 .sum(when(PAYMENT_TYPE).is("creditCard").then(TOTAL).otherwise(0)).as(CARD_PAYMENT) // 计算所有支付类型的总额(可选) .sum(TOTAL).as(TOTAL_AMOUNT); } // 可选:投影操作,调整输出字段顺序与格式 public ProjectionOperation projectionLogic() { return project(STORE_ID, CASH_PAYMENT, CARD_PAYMENT, TOTAL_AMOUNT) .and(STORE_ID).previousOperation(); } // 聚合执行示例 public void executeAggregation() { Aggregation aggregation = newAggregation( groupingLogic(), projectionLogic() // 按需添加 ); // 后续通过mongoTemplate执行聚合,示例: // mongoTemplate.aggregate(aggregation, "your-collection-name", PaymentSummary.class); } } // 对应结果的实体类示例 class PaymentSummary { private String storeId; private Number cashPayment; private Number cardPayment; private Number totalAmount; // Getter、Setter方法 }
代码说明
- 分组维度调整:仅以
storeId作为分组键,确保每个门店只生成一条汇总记录。 - 条件求和逻辑:通过
ConditionalOperators.when判断支付类型,对符合条件的total字段累加,不符合的则加0,实现不同支付类型的单独统计。 - 可选总和计算:直接使用
sum(TOTAL)累加所有支付记录的总额,得到合计值。 - 投影操作:可选用于规范输出字段的顺序,让结果更贴合期望格式。
内容的提问来源于stack exchange,提问作者jarvo69
相关产品推荐
相关产品推荐

