Составной сложный документ Mongodb с вложенными поисками
У меня есть такие коллекции:
Места
{
_id: ObjectId("5acdb8f65ea63a27c1facf86"),
TemplateId: ObjectId("sdfsdfs34234234sdf"),
}
Шаблоны
{
_id: ObjectId("sdfsdfs34234234sdf"),
Type: "Site",
Name: "Site 1",
Sections:[{
id: ObjectId("8asdf89asd8f9sdf"),
Header: "Header1",
FieldItems: [
{
FieldId: ObjectId("jsd32423423423"),
x: 1,
y: 0
},
{
FieldId: ObjectId("2342sdffafdasdfdfs"),
x: 1,
y: 1
}
]
},
(...more sections...)
]
}
Поля
{
_id: ObjectId("jsd32423423423"),
Type: "Phone",
Name: "Phone_Test"
},
{
_id: ObjectId("2342sdffafdasdfdfs"),
Type: "Numeric",
Name: "Number_Test"
}
Я новичок в MongoDB, но потратил пару дней на чтение вопросов и ответов, а также документации. Я использую MongoDB 4.2.6. Я пытаюсь вернуть результат в таком формате:
{
id: ObjectId("5acdb8f65ea63a27c1facf86"),
TemplateId: ObjectId("sdfsdfs34234234sdf"),
Template: {
id: ObjectId("sdfsdfs34234234sdf"),
Type: "Site",
Sections:[{
id: ObjectId("8asdf89asd8f9sdf"),
Header: "Header1",
FieldItems: [
{
FieldId: ObjectId("jsd32423423423"),
x: 1,
y: 0,
Field: {
_id: ObjectId("jsd32423423423"),
Type: "Phone",
Name: "Phone_Test"
}
}, (...)]
}]
}
Я написал агрегированный запрос с вложенными поисками, чтобы получить в основном это, но чтобы заставить его работать, мне пришлось раскрутить разделы и FieldItems . Я не нашел способа получить массивы так, как мне бы хотелось. Я пробовал группу, но возникли проблемы с подмассивами. Я даже не уверен, что это лучший способ получить нужные мне результаты:
db.getCollection("AppSites").aggregate(
[
{
"$lookup" : { "from" : "AppTemplates", "let": {"template_id": "$TemplateId"},
"pipeline": [
{ "$match": { "$expr": { "$eq" : ["$_id", "$$template_id"] } } }, { "$unwind": "$Sections"}, { "$unwind": "$Sections.FieldItems"}, { "$lookup": {
"from": "AppFields",
"let": {"field_id": "$Sections.FieldItems.FieldId"}, "pipeline": [ { "$match": { "$expr": { "$eq": ["$_id", "$$field_id"] } } }
],
"as": "Sections.FieldItems.Field"
}
}
],
"as" : "Templates"
}
}
]
);
Ответы
Вы сделали $unwind
два раза, поэтому вам нужно использовать два $group
.
{
$group: { _id: { secId: "$_id",
fId: "$Sections.id" }, Type: { $first: "$Type" }, Name: { $first: "$Name" }, Header: { $first: "$Sections.Header" }, fieldItems: { $push: "$Sections.FieldItems" } } }, { $group: {
_id: "$_id.secId", Type: { $first: "$Type" }, Name: { $first: "$Name" }, Sections: { $push: {
id: "$_id.fId", Header: "$Header",
fieldItems: "$fieldItems"
}
}
}
}
- Первая группа - для группировки дочерних объектов. Но Type, Name и Header должны быть установлены для родительского и дочернего массивов соответственно.
- Вторая группа - для группировки родительских объектов. Мы получаем все отдельные поля при группировании дочерних элементов. Здесь просто нужно настроить его в правильных рудерах.
Рабочая площадка Mongo
Примечание: когда вы используете $lookup
, он предоставит массив. Но есть места, где вы просто делаете это как объект. Я не знаю, поддерживает ли ты отношения один на один или нет. Если это так, вы можете использовать позиционный оператор в проекции или arrayElemAt