你可以使用:
a $group 将class_id 和$push 分组在一个数组中,这样我们就可以在下一步轻松推断出哪个类“包含”blue。使用$$ROOT 保留当前文档,因为我们需要与class_id 匹配的学生
$match 仅匹配其中包含等级 blue 的课程
$unwind 删除之前的$$ROOT 生成的学生数组
$project 可以很好地重新组织您的文档
查询将是:
db.students.aggregate([{
"$group": {
"_id": "$class_id",
"grades": { "$push": "$grade" },
"students": { "$push": "$$ROOT" }
}
}, {
"$match": {
"grades": { "$all": ["blue","red"] }
}
}, {
"$unwind": "$students"
}, {
"$project": {
"_id": "$students._id",
"class_id": "$students.class_id",
"grade": "$students.grade",
}
}])
如果您需要匹配 ["blue","red"] 以外的其他颜色,您可以在 $match 聚合中添加更多颜色 ($in: ["blue","red","yellow"])
在 PyMongo 中实现它非常简单:
from pymongo import MongoClient
import pprint
db = MongoClient().testDB
pipeline = [ <the_aggregation_query_here> ]
pprint.pprint(list(db.students.aggregate(pipeline)))
另外,要仅匹配属于 classes 集合的学生,请执行 $lookup 并匹配那些不为空的学生。在聚合查询中添加以下内容:
{
$lookup: {
from: "classes",
localField: "class_id",
foreignField: "class_id",
as: "class"
}
}, {
$match: {
"class": { $not: { $size: 0 } }
}
}