Mongodb$graphLookup建立层次结构



我有一个来自mongodb $graphLookup聚合的输出:

db.getCollection('projects').aggregate([
    {
    $lookup: {
      from: "projects",
      localField: "_id",
      foreignField: "parent",
       as: "childrens"
     }
 }
])

{
    "_id" : "1",
    "name" : "Project1",
    "parent" : null,
    "childrens" : [ 
        {
            "_id" : "3",
            "name" : "ProjectForId1",
            "parent" : "1"
        }
    ]
},
{
    "_id" : "3",
    "name" : "ProjectForId1",
    "parent" : "1",
    "childrens" : [ 
        {
            "_id" : "6",
            "name" : "ProjectForId3",
            "parent" : "3"
        }, 
        {
            "_id" : "7",
            "name" : "ProjectForId3",
            "parent" : "3"
        }
    ]
}

我需要在 javascript 中从此输出构建层次结构,或者如果可能的话直接从查询中构建层次结构,因此最终输出应如下所示:

{
    "_id" : "1",
    "name" : "Project1",
    "parent" : null,
    "childrens" : [ 
        {
            "_id" : "3",
            "name" : "ProjectForId1",
            "parent" : "1",
            "childrens" : [ 
                {
                    "_id" : "6",
                    "name" : "ProjectForId3",
                    "parent" : "3"
                }, 
                {
                    "_id" : "7",
                    "name" : "ProjectForId3",
                    "parent" : "3"
                }
            ]
        }
    ]
} 

此外,如果有人有一颗勇敢的心来帮助另一种情况,其中层次结构将通过过滤_id创建:

例如:对于_id = "1"输出将与上述相同,但如果_id 3则最终输出应如下所示:

{
    "_id" : "3",
    "name" : "ProjectForId1",
    "parent" : "1",
    "childrens" : [ 
        {
            "_id" : "6",
            "name" : "ProjectForId3",
            "parent" : "3"
        }, 
        {
            "_id" : "7",
            "name" : "ProjectForId3",
            "parent" : "3"
        }
    ]
}

下面的解决方案或多或少与我过去的答案之一相同,因此您可以在此处获得详尽的解释

db.projects.aggregate([
    {
        $graphLookup: {
            from: "projects",
            startWith: "$_id",
            connectFromField: "_id",
            connectToField: "parent",
            as: "children",
            maxDepth: 4,
            depthField: "level"
        }
    },
    {
        $unwind: "$children"
    },
    {
        $sort: { "children.level": -1 }
    },
    {
        $group: {
            _id: "$_id",
            children: { $push: "$children" }
        }
    },
    {
        $addFields: {
            children: {
                $reduce: {
                    input: "$children",
                    initialValue: {
                        currentLevel: -1,
                        currentLevelProjects: [],
                        previousLevelProjects: []
                    },
                    in: {
                        $let: {
                            vars: {
                                prev: { 
                                    $cond: [ 
                                        { $eq: [ "$$value.currentLevel", "$$this.level" ] }, 
                                        "$$value.previousLevelProjects", 
                                        "$$value.currentLevelProjects" 
                                    ] 
                                },
                                current: { 
                                    $cond: [ 
                                        { $eq: [ "$$value.currentLevel", "$$this.level" ] }, 
                                        "$$value.currentLevelProjects", 
                                        [] 
                                    ] 
                                }
                            },
                            in: {
                                currentLevel: "$$this.level",
                                previousLevelProjects: "$$prev",
                                currentLevelProjects: {
                                    $concatArrays: [
                                        "$$current", 
                                        [
                                            { $mergeObjects: [ 
                                                "$$this", 
                                                { children: { $filter: { input: "$$prev", as: "e", cond: { $eq: [ "$$e.parent", "$$this._id"  ] } } } } 
                                            ] }
                                        ]
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    {
        $addFields: { children: "$children.currentLevelProjects" }
    },
    {
        $match: {
            _id: "1"
        }
    }
])

最后一个阶段应该是过滤,因此您可以在此处获取任何深度级别的数据。

最新更新