You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 23:31:05