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

如何在Spring Boot中使用MongoTemplate实现MongoDB聚合查询?

在Spring Boot中用MongoTemplate实现MongoDB聚合筛选嵌套数组的正确方式

你的问题核心在于普通查询无法过滤嵌套数组中的元素,而且原代码的正则匹配逻辑和Mongo Shell中的操作不一致,再加上实体类映射可能不匹配,导致了空指针异常。下面一步步帮你解决:

为什么原代码不生效?

  1. 普通Query的局限性:你用Criteria.where("listItems.item").regex(...)会返回整个包含符合条件元素的文档,但不会过滤数组里的其他不匹配元素——这和你在Mongo Shell中用$filter实现的数组筛选逻辑完全不同。
  2. 正则匹配逻辑错误:原代码里的^" + item + "$"是精确匹配(要求字符串完全等于item),但你需要的是包含匹配(对应Mongo Shell里的/ja/i),这也是结果不符合预期的原因。
  3. 实体类映射问题:你返回的是ListValue.class,但你的集合是qualification,文档结构包含code、description等顶级字段,这会导致MongoTemplate无法正确映射文档,返回null后触发空指针异常。

正确的聚合实现步骤

1. 定义匹配文档结构的实体类

首先要创建对应qualification集合的实体类,包含嵌套的listItems子对象:

import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.List;

@Document(collection = "qualification")
@Data
public class Qualification {
    private String code;
    private String description;
    private String status;
    private List<ListItem> listItems;
    private String returncode;
    private String message;

    @Data
    public static class ListItem {
        private String itemId;
        private String item;
    }
}

2. 用MongoTemplate实现聚合查询

对应你在Mongo Shell中写的$match + $project聚合管道,用Spring Data的AggregationAPI来实现:

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.ArrayOperators;
import org.springframework.data.mongodb.core.aggregation.MatchOperation;
import org.springframework.data.mongodb.core.aggregation.ProjectionOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Repository;

@Repository
public class QualificationRepository {

    private final MongoTemplate mongoTemplate;

    // 构造注入MongoTemplate
    public QualificationRepository(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    public Qualification getFilteredQualification(String code, String itemPattern) {
        // 1. 构建$match阶段:筛选code匹配的文档
        MatchOperation matchStage = Aggregation.match(Criteria.where("code").is(code));

        // 2. 构建$project阶段:用$filter筛选listItems数组,只保留item匹配正则的元素
        ProjectionOperation projectStage = Aggregation.project("code", "description", "status", "returncode", "message")
                .and(ArrayOperators.Filter.filter("listItems")
                        .as("listItem")
                        .by(Criteria.where("listItem.item").regex(itemPattern, "i").getCriteriaObject()))
                .as("listItems");

        // 组装聚合管道
        Aggregation aggregation = Aggregation.newAggregation(matchStage, projectStage);

        // 执行聚合,返回唯一结果(假设code是唯一标识)
        return mongoTemplate.aggregate(aggregation, "qualification", Qualification.class).getUniqueMappedResult();
    }
}

3. 调用时避免空指针

当没有匹配到任何文档时,getUniqueMappedResult()会返回null,所以调用时一定要做非空判断:

// 示例调用
Qualification result = qualificationRepository.getFilteredQualification("DEVELOPER", "ja");
if (result != null) {
    // 处理筛选后的结果
    System.out.println(result.getListItems()); // 只会包含Java和Javascript的条目
} else {
    // 处理未找到数据的情况
    System.out.println("No matching qualification found");
}

关键细节说明

  • 正则匹配:这里直接传入itemPattern(比如"ja"),对应Mongo Shell里的/ja/i,实现忽略大小写的包含匹配。如果需要精确匹配,再加上^和$。
  • 聚合结果映射:aggregate()方法会将聚合后的文档正确映射到Qualification实体类,解决了原代码中实体类不匹配的问题。
  • 空指针预防:通过非空判断避免返回null时触发的空指针异常,同时也能优雅处理无数据的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:17:41