Mongodb:在聚合中将其用作connectFromField之前计算一个值

时间:2017-11-15 12:34:04

标签: mongodb tree

我有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

1 个答案:

答案 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级深度就足够了: