U maakt een fout vanaf het begin van uw aggregatiepijplijn
$project: {
"tasks" : 1
}
waardoor u al uw gegevens verliest. Dus eerst en vooral moet je het reserveren om:
$project: {
tasks: 1,
doc: {
title: "$title",
order: "$order",
description: "$description",
status: "$status"
}
}
Voer daarna uw $unwind
. uit s zoals u doet in uw vraag:
{$unwind: "$tasks"}, {$unwind: "$tasks.subTasks"}
Doe dan de sortering. U moet het sorteren met samengestelde sleutels doen, anders moet u bestellen op tasks.subTasks.order
wordt niet vastgehouden zodra je sorteert op tasks.order
. Dus:
{$sort: {"tasks.order": -1, "tasks.subTasks.order": 1}}
En dan komt het moeilijke deel. Je moet $group
de resultaten terug, en de eerste stap is om $push
terug naar de subTasks
, maar eerst en vooral moet u opnieuw de taakkenmerken behouden:
$project: {
doc: 1,
task_id: "$tasks._id",
tasks_doc: {
title: "$tasks.title",
description: "$tasks.description",
order: "$tasks.order",
status: "$tasks.status"
},
subTasks: "$tasks.subTasks"
}
...verzamel subTasks
:
$group: {
_id: {
_id: "$_id",
task_id: "$task_id",
doc: "$doc",
task_doc: "$tasks_doc"
},
subTasks: {
$push: "$subTasks"
}
}
En hetzelfde voor de tasks
. Let erop dat tijdens de $group
Als je wilt, moet je ook de task_doc
. terug projecteren attributen:
$group: {
_id: {
_id: "$_id._id",
doc: "$_id.doc"
},
tasks: {
$push: {
_id: "$_id.task_id",
title: "$_id.task_doc.title",
description: "$_id.task_doc.description",
order: "$_id.task_doc.order",
status: "$_id.task_doc.status"
subTasks: "$subTasks"
}
}
}
En projecteer vervolgens de root doc
attributen:
$project: {
_id: "$_id._id",
title: "$_id.doc.title",
description: "$_id.doc.description",
order: "$_id.doc.order",
status: "$_id.doc.status",
tasks: 1
}
Dat is het in principe. Hier is de volledige ruwe aggregatiepijplijn, zodat u kunt testen en zien of u het gewenste resultaat krijgt:
[
{$match: {_id: ObjectId("554a13d4b692088a38f01f3b")}},
{$project: {tasks: 1, doc: {title: "$title", order: "$order", description: "$description", status: "$status"}}},
{$unwind: "$tasks"},
{$unwind: "$tasks.subTasks"},
{$sort: {"tasks.order": -1, "tasks.subTasks.order": 1}},
{$project: {doc: 1, task_id: "$tasks._id", tasks_doc: {title: "$tasks.title", description: "$tasks.description", order: "$tasks.order", status: "$tasks.status"}, subTasks: "$tasks.subTasks"}},
{$group: {_id: {_id: "$_id", task_id: "$task_id", doc: "$doc", task_doc: "$tasks_doc"}, subTasks: {$push: "$subTasks"}}},
{$group: {_id: {_id: "$_id._id", doc: "$_id.doc"}, tasks: {$push: {_id: "$_id.task_id", title: "$_id.task_doc.title", description: "$_id.task_doc.description", order: "$_id.task_doc.order", status: "$_id.task_doc.status", subTasks: "$subTasks"}}}},
{$project: {_id: "$_id._id", title: "$_id.doc.title", description: "$_id.doc.description", order: "$_id.doc.order", status: "$_id.doc.status", tasks: 1}}
]
UPDATE
Als een matrixveld leeg is of niet bestaat (is null
) de $unwind
bewerking op dat veld geeft een leeg resultaat terug
. De oplossing voor deze situatie is in eerste instantie het instellen van de null
/empty veld naar een zero
waarde, bijv. "<empty-array>"
. Merk op dat je dit $project
. moet doen ion voor elke array, vóór zijn $unwind
.
Bekijk dit antwoord
over het gebruik van de $ifNull
exploitant. Bekijk ook de $size
operator hier
.
Nadat je dit deel hebt behandeld, moet je $group
de resultaten terug, en dit kan worden bereikt met behulp van de $cond
operator
, om te controleren tegen de "<empty-array>"
waarde