É
non-trivial
solução. REQUISITOS
1 Precisamos adicionar um campo extra (vamos chamá-lo de
level
) que indica onde o documento está localizado dentro da hierarquia. |root 0
|-child A 1
|--child A_1 2
|-child B 1
2 Precisamos
define
profundidade da hierarquia anterior (por exemplo:max 3) LIMITAÇÃO
Para filtrar de um nível específico, precisamos modificar
root
e children
$match valores.Garanta sempre o nível de hierarquia:
root - 0
children - 1
root - 1
children - 2
SOLUÇÃO
db.documents.aggregate([
{
$facet: {
root: [
{
$match: {
level: 0
}
}
],
children: [
{
$match: {
level: 1
}
},
{
$graphLookup: {
from: "documents",
startWith: "$_id",
connectFromField: "_id",
connectToField: "parentId",
maxDepth: 0,
as: "hierarchy"
}
},
{
$sort: {
_id: 1
}
}
]
}
},
{
$unwind: "$root"
},
{
$project: {
"root._id": 1,
"root.name": 1,
"root.level": 1,
"root.hierarchy": {
$filter: {
input: "$children",
as: "sub_level",
cond: {
$eq: [
"$$sub_level.parentId",
"$root._id"
]
}
}
}
}
},
{
$replaceRoot: {
newRoot: "$root"
}
}
])
MongoPlayground (profundidade máxima:3) | MongoPlayground (profundidade máxima:4)
EXPLICAÇÃO
-
Com$facet
definimos a estrutura de nível.root
todos os diretórios raiz apenas.children
contém todos os filhos com nível 1 + filhos descendentes.
-
Nós$filter
(mesclar) raiz e filhos porparentId
-
Com$project
e$replaceRoot
devolvemos a estrutura original.
LINKS
https://docs.mongodb.com/manual/reference/operator/ agregação/faceta/
https://docs.mongodb.com/manual/ referência/operador/agregação/filtro/
https://docs.mongodb.com/manual/ referência/operador/agregação/substituirRoot/