您需要使用$lookup。就像 SQL 中的“连接”。
但是,首先。你的文件可能会好得多。 schoolRank 集合可以在文档中包含每个学校,而不是包含所有值的唯一数组。
在这里查看your schema 的查询与schoolRank 拆分为diffretend documents 的架构之间的区别。
第二个查询仅返回字段school 匹配的文档。另一个将返回每个文档的整个数组,因为在每个文档中都存在一个字段 school,该字段也存在于 rank 数组中。
因此,对于您的架构,您需要额外的阶段。也许还有另一种更有效的方法,但我不习惯用错误的架构来做$lookup(对不起)。
我试过这个查询:
首先$lookup 加入两个集合(正如我之前所说,加入基本上是将整个数组添加到每个文档中)。
然后是一个额外的阶段,使用 $set 和第一个位置的元素获取从 $lookup 返回的值。
之后,使用$project te查询可以过滤字段rank_school并覆盖它以仅获取字段school与student.school相同的元素。
请注意,使用其他架构可以省略上述步骤。
那么,在$project之后有一个$match阶段来获取rank_school.value大于等于3的文档。
最后阶段是另一个$project 删除字段rank_school。
这是查询:
db.student.aggregate([
{
"$lookup": {
"from": "schoolRank",
"localField": "school",
"foreignField": "rank.school",
"as": "rank_school"
}
},
{
"$set": { "rank_school": { "$arrayElemAt": [ "$rank_school", 0 ] } }
},
{
"$project": {
"_id": "$_id",
"name": "$name",
"school": "$school",
"rank_school": {
"$filter": {
"input": "$rank_school.rank",
"as": "rank_school_filter",
"cond": { "$eq": [ "$$rank_school_filter.school", "$school" ] }
}
}
}
},
{
"$match": { "rank_school.value": { "$gte": 3 } }
},
{
"$project": { "rank_school": 0 }
}
])
例如here。
输出是:
[
{
"_id": ObjectId("5a934e000102030405000003"),
"name": "Mike",
"school": "C"
},
{
"_id": ObjectId("5a934e000102030405000004"),
"name": "Tom",
"school": "D"
}
]