如何在Quarkus的PanacheMongoRepository中实现MongoDB聚合、$sum与过滤
在Quarkus PanacheMongoRepository中实现指定MongoDB聚合查询
1. 定义实体类
先创建与salestransactions集合对应的实体,字段类型需匹配MongoDB存储类型:
import io.quarkus.mongodb.panache.PanacheMongoEntity; import java.time.Instant; import java.math.BigDecimal; public class SalesTransaction extends PanacheMongoEntity { public String userId; public Instant timestamp; // 对应MongoDB的ISODate类型 public BigDecimal revenue; // 用BigDecimal处理金额避免精度问题 }
2. 实现Repository聚合方法
在继承PanacheMongoRepository的仓库类中,利用MongoDB Java驱动的聚合API复现mongosh中的查询逻辑:
import io.quarkus.mongodb.panache.PanacheMongoRepository; import jakarta.enterprise.context.ApplicationScoped; import java.time.Instant; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import org.bson.Document; import static com.mongodb.client.model.Aggregates.group; import static com.mongodb.client.model.Aggregates.match; import static com.mongodb.client.model.Accumulators.*; import static com.mongodb.client.model.Filters.gte; import static com.mongodb.client.model.Filters.lte; import static com.mongodb.client.model.Filters.gt; @ApplicationScoped public class SalesTransactionRepository implements PanacheMongoRepository<SalesTransaction> { public List<Document> getUserSalesStats(Instant timeStart, Instant timeEnd, BigDecimal minTotalSum) { return mongoCollection().aggregate(List.of( // 筛选时间范围内的交易记录 match( gte("timestamp", timeStart), lte("timestamp", timeEnd) ), // 按userId分组,计算聚合指标 group( new Document("userId", "$userId"), min("minimum", "$revenue"), max("maximum", "$revenue"), sum("sum", "$revenue"), avg("avg", "$revenue") ), // 过滤总和超过阈值的用户 match(gt("sum", minTotalSum)) )).into(new ArrayList<>()); } }
3. 业务层调用示例
在资源类或业务服务中调用该方法,传入参数即可得到结果:
import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import java.time.Instant; import java.math.BigDecimal; import java.util.List; import org.bson.Document; @Path("/sales/user-stats") public class SalesStatsResource { @Inject SalesTransactionRepository salesRepo; @GET public List<Document> fetchUserStats() { // 构造与mongosh示例一致的时间范围 Instant startTime = Instant.parse("2020-01-01T19:28:38.000Z"); Instant endTime = Instant.parse("2020-03-01T19:28:38.000Z"); // 设置总和阈值为10 BigDecimal sumThreshold = new BigDecimal("10"); return salesRepo.getUserSalesStats(startTime, endTime, sumThreshold); } }
补充说明
- 直接通过
mongoCollection()获取底层MongoDB集合,使用官方驱动的聚合API构建管道,逻辑与mongosh查询完全对齐 - 如果MongoDB中
revenue存储的是Double类型,可将实体类和方法中的BigDecimal替换为Double - 返回的
Document可直接序列化为JSON,也可以映射到自定义DTO类(例如创建UserSalesStats类,通过document.to(UserSalesStats.class)转换)
内容的提问来源于stack exchange,提问作者Marcus Pillawa
相关产品推荐
相关产品推荐

