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

如何在Repository层将三个逻辑合并为单条MongoDB查询返回ID差集

实现方案

核心思路是利用MongoDB聚合管道的$unionWith、$group、$match操作,全程在MongoDB服务端完成差集计算,不需要拉取全量ID到应用内存,仅需一次请求即可拿到结果,性能和代码整洁度都远高于原有实现。


完整Repository层代码

import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;

// 单查询方法直接返回两个集合的ID差集
public List<String> getLecturerIdDifferenceList() {
    Aggregation aggregation = newAggregation(
        // 第一步:筛选brlnlecturers集合中ACTIVE状态的文档,仅提取_id字段
        match(Criteria.where("status").is("ACTIVE")),
        project("_id"),
        // 第二步:合并lndlecturers集合的所有_id字段
        unionWith("lndlecturers", project("_id")),
        // 第三步:按_id分组,统计每个ID在两个集合中总共出现的次数
        group("_id").count().as("count"),
        // 第四步:筛选仅出现1次的ID,也就是只存在于其中一个集合的差集元素
        match(Criteria.where("count").is(1)),
        // 第五步:格式化输出字段
        project().and("_id").as("id")
    );

    AggregationResults<IdResult> results = mongoTemplate.aggregate(aggregation, "brlnlecturers", IdResult.class);
    return results.getMappedResults().stream()
        .map(IdResult::getId)
        .map(Object::toString)
        .toList();
}

// 聚合结果映射内部类,也可以直接用Map接收,单独定义更清晰
private static class IdResult {
    private Object id;
    public Object getId() { return id; }
    public void setId(Object id) { this.id = id; }
}

自定义调整说明

如果不需要对称差集,仅需要单向差集(比如只返回lndlecturers有但brlnlecturers没有的ID),可以用左连接的方式实现:

public List<String> getLndExclusiveLecturerIds() {
    Aggregation aggregation = newAggregation(
        // 取lndlecturers集合所有_id
        project("_id"),
        // 左连接brlnlecturers集合中状态为ACTIVE的同_id记录
        lookup("brlnlecturers", "_id", "_id", "matched"),
        // 筛选匹配结果为空的记录,就是lnd存在但brln不存在的ID
        match(Criteria.where("matched").size(0)),
        project("_id")
    );
    AggregationResults<IdResult> results = mongoTemplate.aggregate(aggregation, "lndlecturers", IdResult.class);
    return results.getMappedResults().stream()
        .map(IdResult::getId)
        .map(Object::toString)
        .toList();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 16:18:01