Я работаю над университетским проектом, и мне нужно заполнить массив объектов идентификаторами ObjectId, но я не могу использовать mongoose в своем проекте. У меня есть две коллекции - тематическая и учебная программа.
Пример документа StudyProgram:
{
_id: ObjectId('111'),
name: "Study program 1"
description: "Lorem ipsum dolor sit amet",
language: "en",
subjects: [
{
id: ObjectId('222'),
optionality: "selective",
credits: 8,
},
{
id: ObjectId('333'),
optionality: "selective",
credits: 5
},
],
}
Примеры тематических документов:
{
_id: ObjectId('222'),
name: "Subject A",
description: "Subject A description.",
},
{
_id: ObjectId('333'),
name: "Subject B",
description: "Subject B description.",
}
Мне нужно заполнить объекты в массиве subjects соответствующими документами из предметной коллекции на основе id. В основном то, что я ищу, это этот результат:
{
_id: ObjectId('111'),
name: "Study program 1"
description: "Lorem ipsum dolor sit amet",
language: "en",
subjects: [
{
_id: ObjectId('222'),
name: "Subject A",
description: "Subject A description.",
optionality: "selective",
credits: 8,
},
{
_id: ObjectId('333'),
name: "Subject B",
description: "Subject B description.",
optionality: "selective",
credits: 5
},
],
}
До сих пор я пытался использовать следующий $lookup:
{
$lookup: {
from: "subject",
localField: "subjects.id",
foreignField: "_id",
as: "subjects",
}
}
Но это удаляет атрибуты optionality и credits. Есть ли способ добиться этого без использования мангуста? Спасибо.
Вот один из способов сделать это.
db.studyProgram.aggregate([
{
"$lookup": {
"from": "subject",
"localField": "subjects.id",
"foreignField": "_id",
"as": "subjectDocs"
}
},
{
"$set": {
"subjects": {
"$map": {
"input": "$subjects",
"as": "subject",
"in": {
"$mergeObjects": [
{
"$first": {
"$filter": {
"input": "$subjectDocs",
"as": "doc",
"cond": {"$eq": ["$$doc._id", "$$subject.id"]}
}
}
},
{
"optionality": "$$subject.optionality",
"credits": "$$subject.credits"
}
]
}
}
},
"subjectDocs": "$$REMOVE"
}
}
])
Попробуйте на mongoplayground.net.
Если "$first" недоступен, попросите вашего системного администратора обновить MongoDB! До тех пор это, вероятно, будет работать.
db.studyProgram.aggregate([
{
"$lookup": {
"from": "subject",
"localField": "subjects.id",
"foreignField": "_id",
"as": "subjectDocs"
}
},
{
"$set": {
"subjects": {
"$map": {
"input": "$subjects",
"as": "subject",
"in": {
"$mergeObjects": [
{
"$arrayElemAt": [
{
"$filter": {
"input": "$subjectDocs",
"as": "doc",
"cond": {"$eq": ["$$doc._id", "$$subject.id"]}
}
},
0
]
},
{
"optionality": "$$subject.optionality",
"credits": "$$subject.credits"
}
]
}
}
},
"subjectDocs": "$$REMOVE"
}
}
])
Попробуйте на mongoplayground.net.
@MarekBalvín Да, я вижу, "$first" доступен только в "$group" с этой версией. Я обновил конвейер агрегации с помощью "$arrayElemAt". Смотрите обновленный ответ.
Большое спасибо, я попробовал это на mongoplayground, и это работает. Однако, когда я использую его в своем проекте, я получаю сообщение об ошибке: «Нераспознанное выражение «$ first»». Я полагаю, это потому, что я использую Mongo версии 4.11.0, а $first недоступен в этой версии. Есть ли другой оператор, который я могу использовать вместо этого?