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

如何通过MongoOperations单次数据库请求获取多分组列表?

当然可以!用MongoDB聚合框架实现单次请求分组查询

你当前的代码通过多次数据库查询来获取每个车型的前5条请求,确实可以通过MongoDB聚合框架配合MongoOperations改成单次数据库请求完成,这样能显著减少数据库交互次数,提升接口性能。

核心思路

利用聚合管道的以下阶段组合实现需求:

  1. $match:先过滤出unlock: true的有效请求,同时可以指定需要的车型(如果不需要全量车型的话)
  2. $sort:如果你的“last five”指的是最新的5条记录,需要先按时间字段(比如createTime)倒序排序,确保取到最新数据(你当前的代码没做排序,这可能是个小隐患哦)
  3. $project:只保留业务需要的字段(对应你原来的query.fields().include()逻辑)
  4. $group:按vehicleTypeEnum分组,将每个组的文档存入数组,再用$slice截取前5条
  5. $project:将结果整理成更符合你当前Map<String, List<Request>>格式的结构

具体代码实现

下面是完整的改造示例:

public ResponseEntity<?> getFiveLastRequestOfEachVehicleType() {
    ResponseContent content = getResponseContent();
    
    // 1. 构建聚合管道
    Aggregation aggregation = Aggregation.newAggregation(
        // 筛选unlock=true的记录,同时指定需要的车型
        Aggregation.match(Criteria.where("unlock").is(true)
            .and("vehicleTypeEnum").in(VehicleTypeEnum.NEISAN, VehicleTypeEnum.BADSAN, VehicleTypeEnum.BUJE)),
        // 按时间倒序(假设你有createTime字段,根据实际字段调整),确保取最新的5条
        Aggregation.sort(Sort.Direction.DESC, "createTime"),
        // 只保留需要的字段
        Aggregation.project("id", "goodsTypeTitle", "originCityTitle", "price")
            .and("vehicleTypeEnum").previousOperation(),
        // 按车型分组,截取每个组的前5条记录
        Aggregation.group("vehicleTypeEnum")
            .push(Aggregation.ROOT).as("requests")
            .slice("requests", 5),
        // 将结果转换为方便转Map的格式
        Aggregation.project("requests")
            .and("_id").as("vehicleType")
    );

    // 2. 执行聚合查询
    AggregationResults<VehicleTypeRequestGroup> results = mongoOperations.aggregate(
        aggregation,
        "request", // 你的集合名称,对应Request.class的映射集合
        VehicleTypeRequestGroup.class
    );

    // 3. 将结果转换为你需要的Map<String, List<Request>>格式
    Map<String, List<Request>> map = results.getMappedResults().stream()
        .collect(Collectors.toMap(
            group -> group.getVehicleType().name(),
            VehicleTypeRequestGroup::getRequests
        ));

    content.setData(map);
    return getReturn(content);
}

// 用于接收聚合结果的DTO类
static class VehicleTypeRequestGroup {
    private VehicleTypeEnum vehicleType;
    private List<Request> requests;

    // Getters and Setters
    public VehicleTypeEnum getVehicleType() { return vehicleType; }
    public void setVehicleType(VehicleTypeEnum vehicleType) { this.vehicleType = vehicleType; }
    public List<Request> getRequests() { return requests; }
    public void setRequests(List<Request> requests) { this.requests = requests; }
}

关键细节说明

  • 排序的重要性:如果你需要的是“最近的5条”,一定要加上$sort阶段,否则MongoDB返回的前5条是无序的,可能不符合预期。
  • 字段投影:$project阶段严格控制返回字段,和你原来的query.fields().include()逻辑保持一致,避免不必要的数据传输。
  • 分组截取:$group阶段用$push收集文档,再通过$slice直接截取前5条,替代原来的多次limit(5)查询。

对比原代码的优势

  • 从3次数据库请求减少到1次,降低了网络开销和数据库连接压力
  • 聚合逻辑在数据库端执行,效率更高,尤其当数据量较大时优势明显
  • 代码结构更简洁,避免重复的Query构建逻辑

内容的提问来源于stack exchange,提问作者Mohsen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:52:39