Documento complesso aggregato Mongodb con ricerche annidate
Ho queste collezioni:
Siti
{
_id: ObjectId("5acdb8f65ea63a27c1facf86"),
TemplateId: ObjectId("sdfsdfs34234234sdf"),
}
Modelli
{
_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...)
]
}
Campi
{
_id: ObjectId("jsd32423423423"),
Type: "Phone",
Name: "Phone_Test"
},
{
_id: ObjectId("2342sdffafdasdfdfs"),
Type: "Numeric",
Name: "Number_Test"
}
Sono nuovo in MongoDB, ma ho impiegato un paio di giorni a leggere domande e risposte, oltre alla documentazione. Sto usando MongoDB 4.2.6. Sto cercando di restituire un risultato formattato in questo modo:
{
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"
}
}, (...)]
}]
}
Ho scritto una query aggregata con ricerche annidate per portarmi principalmente lì, ma per farlo funzionare ho dovuto rilassare Sections e FieldItems . Non ho trovato un modo per portare gli array nel modo in cui li vorrei. Ho provato il gruppo ma ho avuto problemi con gli array secondari. Non sono nemmeno sicuro che questo sia il modo migliore per ottenere i risultati di cui ho bisogno:
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"
}
}
]
);
Risposte
Hai fatto $unwind
due volte, quindi devi usarne due $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"
}
}
}
}
- Primo gruppo - per raggruppare oggetti figlio. Ma Type, Name e Header devono essere impostati rispettivamente su parent e child array.
- Secondo gruppo: per raggruppare gli oggetti padre. Otteniamo tutti i campi autonomi durante il raggruppamento del bambino. Qui abbiamo solo bisogno di impostarlo negli oreder corretti.
Parco giochi Mongo funzionante
Nota: quando si utilizza $lookup
, fornirà un array. Ma ci sono alcuni posti in cui lo crei come oggetto. Non so se ti unisci in una relazione uno a uno o no. In tal caso è possibile utilizzare l' operatore di posizione in proiezione o arrayElemAt