Je to non-trivial
řešení.
POŽADAVKY
1 Potřebujeme přidat další pole (říkejme mu level
), který označuje, kde se dokument nachází v hierarchii.
|root 0
|-child A 1
|--child A_1 2
|-child B 1
2 Musíme define
dříve hloubka hierarchie (například:max 3)
OMEZENÍ
Abychom mohli filtrovat z konkrétní úrovně, musíme upravit root
a children
$match hodnoty.
Vždy zajistěte úroveň hierarchie:
root - 0
children - 1
root - 1
children - 2
ŘEŠENÍ
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 (maximální hloubka:3) | MongoPlayground (maximální hloubka:4)
VYSVĚTLENÍ
-
S
$facet
definujeme strukturu úrovní.root
pouze celý kořenový adresář.children
obsahuje všechny děti s úrovní 1 + potomky dětí. -
My
$filter
(sloučit) root a děti podleparentId
-
S
$project
a$replaceRoot
vrátíme původní strukturu.
ODKAZY
https://docs.mongodb.com/manual/reference/operator/ agregace/fazeta/
https://docs.mongodb.com/manual/ reference/operátor/agregace/filtr/
https://docs.mongodb.com/manual/ reference/operator/agregation/replaceRoot/