随着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
List
// 聚合查询
List
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
for (Iterator
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;