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 getCorrectingIdByTutorAndTeacher(Long tutorId, Long schoolId, Long teacherId) {
        List list = new ArrayList<>();
        // 聚合查询
        List operations = new ArrayList();
        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 result = mongoTemplate.aggregate(aggregation, Correcting.class, Document.class);
        for (Iterator 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;

        

 

你可能感兴趣的:(mongoDB)