我有mongo树结构,如下所示:
{"_id":uid1,"parent": null, "path": "#uid1", "name": "a"}
{"_id":uid2,"parent": "uid1", "path": "#uid1#uid2", "name": "b"}
{"_id":uid3,"parent": "uid1", "path": "#uid1#uid3", "name": "c"}
{"_id":uid4,"parent": "uid2", "path": "#uid1#uid2#uid4", "name": "1"}
{"_id":uid5,"parent": "uid2", "path": "#uid1#uid2#uid5", "name": "2"}
{"_id":uid6,"parent": "uid1", "path": "#uid1#uid6", "name": "1"}
{"_id":uid7,"parent": "uid6", "path": "#uid1#uid6#uid7", "name": "x"}
其中每个节点都由其唯一的ID x 表示,并且由于其父级的uid而定位。每次修改节点的父节点时,它的路径和子节点的路径都会自动修改(在mongoose pre-save中)。
上面的例子可以表示如下:
a
|_b
| |_1
| |_2
|_c
|_1
|_x
我的目标是构建一个只获取指定节点下的叶子的请求。
如果我将父路径存储在字段parent中而不是仅存储父标识符,我可以使用以下请求将其存储起来:
db.tree.aggregate([
{$match:{"parent": {$regex:"^#uid1#uid2"}}},
{$graphLookup:{
from:"tree",
startWith:"$path",
connectFromField:"path",
connectToField:"parent",
as:"dep"}},
{$match:{dep:[]}},
{$project:{"_id":0, path:1}}
])
在我之前的问题中已经回答:Mongodb: get only leaves of tree
问题是我没有。
所以我必须以某种方式转换我的请求中的'connectToField',以便它代表我父节点的路径而不是我父节点的id。有没有人知道如何做到这一点?
这个问题是我上一个问题的重写版本:previous version
答案 0 :(得分:1)
您无需计算任何内容,也无需依赖path
。
它是https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/的确切用例。 { $match: { dep: [] } }
阶段返回没有子节点的节点,即叶子。
db.tree.aggregate([
{ $graphLookup: {
from:"tree",
startWith:"$_id",
connectFromField:"_id",
connectToField:"parent",
as:"dep",
maxDepth: 1
} },
{ $match: { dep: [] } },
])
添加了 maxDepth: 1
以加快速度。一旦节点有一个直接的孩子你就不关心分支的其余部分,所以直接孩子的1级深度就足够了: