问题
I have the following collection representing the directory structure.
I'd like to write an aggregation query that will return all child directory IDs starting from a certain point.
For example:
Starting from root: results: child_A, child_B, child_A_1
Starting from child_a: results: child_A_1
I've created the following query (in Mongo 4.2) according to the docs, but I'm unable to run it successfully.
[{
$match: {
_id: ObjectId('5de7a00bf3663d0805644b91')
}
}, {
$graphLookup: {
from: 'documents',
startWith: '$_id',
connectFromField: '_id',
connectToField: 'parentId',
as: 'hierarchy'
}
}]
How can I solve that issue?
回答1:
It is non-trivial
solution.
REQUIREMENTS
1 We need to add extra field (let's call it level
) which indicates where document is located inside hierarchy.
|root 0
|-child A 1
|--child A_1 2
|-child B 1
2 We need to define
previously hierarchy depth (for instance: max 3)
LIMITATION
In order to filter from specific level, we need to modify root
and children
$match values.
Ensure always hierarchy level:
root - 0
children - 1
root - 1
children - 2
SOLUTION
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 (max depth: 3) | MongoPlayground (max depth: 4)
EXPLANATION
With
$facet
we define level structure.root
all root directory only.children
contains all children with level 1 + children descendants.We
$filter
(merge) root and children byparentId
With
$project
and$replaceRoot
we return original structure.
LINKS
https://docs.mongodb.com/manual/reference/operator/aggregation/facet/
https://docs.mongodb.com/manual/reference/operator/aggregation/filter/
https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/
来源:https://stackoverflow.com/questions/59245431/getting-ancestors-in-mongodb-using-tree-structure