我有两个收藏-
学生合集(学生文档样本)
{
'id': '123',
'name': 'john',
'age': 25,
'fav_colors': ['red', 'black'],
'marks_in_subjects': [
{
'marks': 90,
'subject_id': 'abc'
},
{
'marks': 92,
'subject_id': 'def'
}
]
}
学科集合(2个样本文档)
{
'id': 'abc',
'name': 'math'
},
{
'id': 'def',
'name': 'physics'
}
当我查询id:'123'的学生文档时,我希望结果输出为:
{
'id': '123',
'name': 'john',
'age': 25,
'fav_colors': ['red', 'black'],
'marks_in_subjects': [
{
'marks': 90,
'subject_id': 'abc',
'subject_name': 'math'
},
{
'marks': 92,
'subject_id': 'def',
'subject_name': 'physics'
}
]
}
现在,我阅读了MongoDB聚合管道和运算符文档,但我仍然不知道如何实现这一点。疑问仍然存在,因为我甚至不确定在mongo聚合管道的帮助下是否可能实现这一点,因为JOIN发生在学生文档中数组字段的每个元素上。
如果有人能帮上忙就太好了谢谢
$match
你的条件$lookup
带有主题
集合$addFields
从返回主题name
$group
通过id
重建marks_in_subjects
数组,并使用$first
运算符db.students.aggregate([
{ $match: { id: "123" } },
{ $unwind: "$marks_in_subjects" },
{
$lookup: {
from: "subjects",
localField: "marks_in_subjects.subject_id",
foreignField: "id",
as: "marks_in_subjects.subject_name"
}
},
{
$addFields: {
"marks_in_subjects.subject_name": {
$arrayElemAt: ["$marks_in_subjects.subject_name.name", 0]
}
}
},
{
$group: {
_id: "$id",
name: { $first: "$name" },
age: { $first: "$age" },
fav_colors: { $first: "$fav_colors" },
marks_in_subjects: { $push: "$marks_in_subjects" }
}
}
])
游乐场
没有$un转
阶段的第二个选项,
$match
你的条件$lookup
带有主题
集合$addFields
从主题
获取主题名称
$map
迭代marks_in_subjects
数组的循环$duce
迭代主题
数组的循环,并检查subject_id
是否匹配,然后返回主题名称
$mergeObject
合并marks_in_subjects
的当前对象和新字段subject_name
db.students.aggregate([
{ $match: { id: "123" } },
{
$lookup: {
from: "subjects",
localField: "marks_in_subjects.subject_id",
foreignField: "id",
as: "subjects"
}
},
{
$addFields: {
marks_in_subjects: {
$map: {
input: "$marks_in_subjects",
as: "m",
in: {
$mergeObjects: [
"$$m",
{
subject_name: {
$reduce: {
input: "$subjects",
initialValue: "",
in: {
$cond: [{ $eq: ["$$this.id", "$$m.subject_id"]}, "$$this.name", "$$value"]
}
}
}
}
]
}
}
}
}
},
{ $unset: "subjects" }
])
游乐场
演示-https://mongoplayground.net/p/H5fHpfWz5VH
db.Students.aggregate([
{
$unwind: "$marks_in_subjects" // break into individual documents
},
{
"$lookup": { // get subject details
"from": "Subjects",
"localField": "marks_in_subjects.subject_id",
"foreignField": "id",
"as": "subjects"
}
},
{
$set: { // set name
"marks_in_subjects.name": "subjects.0.name" // pick value from 0 index
}
},
{
$group: { // join document back by id
_id: "$_id",
marks_in_subjects: { $push: "$marks_in_subjects" }
}
}
])