如下面代码,需要对mongo集合中的price汇总相加,price是Bigdecimal类型,在mongodb中是以字符串的形式存储的("price" : "1.500000"):
List<AggregationOperation> operations = new ArrayList<>();
operations.add(Aggregation.match(Criteria.where("pt").is(pt)));
// 将字符串字段转换为double
AggregationOperation projectToDouble = project("pt", "account_id", "status", "total_count", "succ_count", "fail_count", "unknown_count", "price")
.and(ConvertOperators.Convert.convertValueOf("price").to("double")).as("price");
operations.add(projectToDouble);
GroupOperation operation = Aggregation.group("pt", "account_id")
.count().as("total_count")
.sum(ConditionalOperators.when(Criteria.where("status").is(0)).then(1).otherwise(0)).as("succ_count")
.sum(ConditionalOperators.when(Criteria.where("status").is(1)).then(1).otherwise(0)).as("fail_count")
.sum(ConditionalOperators.when(Criteria.where("status").is(2)).then(1).otherwise(0)).as("unknown_count")
.sum("price").as("price")
.first("pt").as("pt")
.first("account_id").as("accountId");
operations.add(operation);
Aggregation aggregation = Aggregation.newAggregation(operations);
AggregationResults<DayStat> results = mongoTemplate.aggregate(aggregation, Record.COLLECTION_NAME, DayStat.class);
List<DayStat> list = results.getMappedResults();
log.info("DayStat: {}", JSONUtil.toJsonStr(list));
注意status要放在project里面,否则succCount、failCount、unknownCount会为0
@Data
public class DayStat {
private Integer pt;
private Long accountId;
private Long totalCount;
private Long succCount;
private Long failCount;
private Long unknownCount;
private BigDecimal price;
}
输出结果:
DayStat: [{"pt":20240806,"accountId":9000000123,"totalCount":2,"succCount":0,"failCount":2,"unknownCount":0,"price":1.6}]
补充,如果status=0想取某列的值,可以改成下面代码:
GroupOperation operation = Aggregation.group("pt", "account_id")
.sum("charge_count").as("total_count")
.sum(ConditionalOperators.when(Criteria.where("status").is(0)).thenValueOf("$charge_count").otherwise(0)).as("succ_count")
.sum(ConditionalOperators.when(Criteria.where("status").is(1)).thenValueOf("$charge_count").otherwise(0)).as("fail_count")
.sum(ConditionalOperators.when(Criteria.where("status").is(2)).thenValueOf("$charge_count").otherwise(0)).as("unknown_count")
.sum("price").as("price")
.first("pt").as("pt")
.first("account_id").as("accountId");
operations.add(operation);