[英]MongoDB Aggregation for every element of array field of a document
I have 2 collections -我有 2 个 collections -
Student collection (sample student document)学生合集(学生文件样本)
{
'id': '123',
'name': 'john',
'age': 25,
'fav_colors': ['red', 'black'],
'marks_in_subjects': [
{
'marks': 90,
'subject_id': 'abc'
},
{
'marks': 92,
'subject_id': 'def'
}
]
}
Subjects collection (2 sample documents)主题集合(2 个样本文件)
{
'id': 'abc',
'name': 'math'
},
{
'id': 'def',
'name': 'physics'
}
When I query for student document for id: '123', I want the resulting output as:当我查询 id: '123' 的学生文档时,我希望得到的 output 为:
{
'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'
}
]
}
Now, I read the MongoDB aggregation pipelines and operators document, still, I am clueless as to how to achieve this.现在,我阅读了 MongoDB 聚合管道和操作员文档,但我仍然对如何实现这一点一无所知。 The doubt persists because I am not even sure if this is possible with the help of mongo aggregation pipelines since JOIN happens here for every element of the array field in the student document.疑问仍然存在,因为我什至不确定这是否可以在 mongo 聚合管道的帮助下实现,因为 JOIN 发生在学生文档中数组字段的每个元素的此处。
It would be really helpful if anyone can help here.如果有人可以在这里提供帮助,那将非常有帮助。 Thanks谢谢
Demo - https://mongoplayground.net/p/H5fHpfWz5VH演示 - 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" }
}
}
])
$match
you conditions $match
你的条件$unwind
deconstruct marks_in_subjects
array $unwind
解构marks_in_subjects
数组$lookup
with subjects
collection $lookup
与subjects
集合$addFields
to get first element name
from return subject $addFields
从返回主题中获取第一个元素name
$group
by id
and reconstruct marks_in_subjects
array and also add your required field of root document using $first
operator $group
by 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" }
}
}
])
Second option without $unwind
stage,没有$unwind
阶段的第二个选项,
$match
you conditions $match
你的条件$lookup
with subjects
collection $lookup
与subjects
集合$addFields
to get subject name from subjects
$addFields
从subjects
中获取主题名称
$map
to iterate loop of marks_in_subjects
array $map
迭代marks_in_subjects
数组的循环$reduce
to iterate loop of subjects
array and check condition if subject_id
match then return subject name
$reduce
迭代subjects
数组的循环并检查条件是否subject_id
匹配然后返回主题name
$mergeObjects
to merge current object of marks_in_subjects
and new field subject_name
$mergeObjects
合并当前 object 的marks_in_subjects
和新字段subject_name
$unset
to remove subjects
array because its not needed now $unset
删除subjects
数组,因为它现在不需要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" }
])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.