MongoDB-如何在多个本地字段上$lookup



我必须在MongoDB中编写一个聚合查询,其中从源集合到目标集合的$lookup可以来自多个字段。即来自源集合的多个字段(所有ID(可以链接到目标集合中的单个字段。

换句话说,我的$lookup中的localfield具有$or条件:

学生:

{
"_id": : {
"$oid": "61c32b08c6056d28db6550b5"
},
"name": "Jack Sparrow",
"course1": : {
"$oid": "82d77b08c6056d28db65ca98"
},
"course2": : {
"$oid": "45d22b08c6056d28db688013"
},
"course3": : {
"$oid": "98a72b08c6056d28db6561d6"
},
"course4": : {
"$oid": "10b22b08c6056d28db6576b1"
}
}

查询:

{
$lookup: {
'from': 'courses', 
'localField': 'course1', 'course2', 'course3', 'course4' 
'foreignField': '_id', 
'as': 'studentCourses'
}
}

在这种情况下,源集合表示students,而目标集合是courses。源表中的课程数量可以最小为1,最大为4。其中任何一个都可以与课程集合中的课程相关。

我怎样才能做到这一点?

localField只能支持string类型的值,该值表示字段名称。

在查找带管道的$lookup时,通过将这些course字段设置为courses数组,并在查找管道中使用$in运算符执行筛选。

db.students.aggregate([
{
$lookup: {
"from": "courses",
"let": {
courses: [
"$course1",
"$course2",
"$course3",
"$course4"
]
},
"pipeline": [
{
$match: {
$expr: {
$in: [
"$_id",
"$$courses"
]
}
}
}
],
"as": "studentCourses"
}
}
])

演示@Mongo Playground


意见:

认为你的学生模式不是一个好的设计。你可能会想,学生们可能会选修不同数量的课程。可能引用的"课程"字段可能不存在。或者,如果每次都添加/删除了"课程"字段,则需要再次修改查询。

您应该考虑一个course数组字段来存储这些course<X>id

您可以参考下面的查询,而不是硬编码字段名称,我们用包含前缀的字段获得值:";课程";。

db.students.aggregate([
{
$lookup: {
"from": "courses",
"let": {
courses: {
$reduce: {
input: {
$filter: {
input: {
$objectToArray: "$$ROOT"
},
cond: {
"$regexMatch": {
"input": "$$this.k",
"regex": "^course[\d]$"
}
}
}
},
initialValue: [],
in: {
$concatArrays: [
"$$value",
[
"$$this.v"
]
]
}
}
}
},
"pipeline": [
{
$match: {
$expr: {
$in: [
"$_id",
"$$courses"
]
}
}
}
],
"as": "studentCourses"
}
}
])

演示2@Mongo Playground

最新更新