MongoDB聚合查询之两个字段关联lookup

        随着no-sql数据库的发展,mongoDB已经被越来越多的项目使用,正好近期一个项目使用了mongoDB,项目需求使用mongoDB进行两张表两个字段关联查询,翻查了很多资料,终于找到了解决方案。    

        表A: projectId  studentId    tutorId    schoolId       表B:  projectId   studentId  correctStatus

                   项目A      学生A         教务A     学校A                       项目A        学生A       已批改

                   项目A      学生B         教务A    学校A                       项目A        学生B        已批改

                   项目B      学生B         教务B     学校A                      项目B        学生B        未批改

                   项目B     学生C          教务A     学校A                       项目B        学生C        未批改 

    项目需要查询教务A在A项目下所负责学生的作业批改记录,这时候需要对表A和表B进行projectId和studentId进行关联查询,翻阅了大量资料,发现mongoDB的lookup仅支持单字段关联(此时我多么希望使用关系型数据库来查询)。然而,项目不能因为这个问题卡住,只能继续翻阅资料,所幸在stackoverflow上凭着我蹩脚的英文水平看到了mongoDB原生聚合查询的sql:

 db.表B.aggregate([
    {
        "$lookup": {
   "from": "表A",//关联表
    "localField": "projectId",//主键
    "foreignField": "projectId",//外键
    "as": "c2"
          }
    },
    {
        "$unwind": "$c2"//打散
    },
    {
        "$project": {//指定输出字段
    "studentIdEq": {
        "$eq": ["$studentId", "$c2.studentId"]
     },
    "tutorId": "$c2.tutorId",
    "correctTime": "$correctTime",
    "schoolId": "$c2.schoolId"
          }
    },
    {
        "$match": {//where条件
    "studentIdEq": {
         "$eq": true
     },
    "tutorId": 1000177842,
    "correctTime": null
          }
    }
])

那么问题又来,如何将这个sql能在java代码中使用呢?经过查阅mongoTemplate源码发现,Aggregation.project()
                .andExpression()这是可以使用表达式的,至此问题得以解决,上源码:

    /**
     * 两个字段关联表查询(根据教务查询其管理学生的作业记录)
     * 
     * @param tutorId
     * @param schoolId
     * @return
     */
    public List<String> getCorrectingIdByTutorAndTeacher(Long tutorId, Long schoolId, Long teacherId) {
        List<String> list = new ArrayList<>();
        // 聚合查询
        List<AggregationOperation> operations = new ArrayList<AggregationOperation>();
        operations.add(Aggregation.lookup("ProjectStudent", "projectId", "projectId", "c2"));
        operations.add(Aggregation.unwind("c2"));
        operations.add(Aggregation.project("c2.tutorId", "c2.schoolId", "correctTime", "teacherId")
                .andExpression("eq(studentId,c2.studentId)").as("stuFilter"));
        Criteria c1 = Criteria.where("stuFilter").is(true);
        Criteria c2 = Criteria.where("tutorId").is(tutorId);
        Criteria c3 = Criteria.where("schoolId").is(schoolId);
        Criteria c4 = Criteria.where("teacherId").is(teacherId);
        Criteria c = new Criteria();
        c.andOperator(c1, c2, c3, c4);
        operations.add(Aggregation.match(c));
        Aggregation aggregation = Aggregation.newAggregation(operations);
        AggregationResults<Document> result = mongoTemplate.aggregate(aggregation, Correcting.class, Document.class);
        for (Iterator<Document> iterator = result.iterator(); iterator.hasNext();) {
            Document obj = iterator.next();
            if (null != obj.get(ID)) {
                list.add(obj.get(ID).toString());
            }
        }
        return list;
    }

引用jar包

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

        

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值