【问题标题】:MongoDB $graphLookup get children all levels deep - nested resultMongoDB $graphLookup 获取所有级别的子级 - 嵌套结果
【发布时间】:2019-03-08 18:15:00
【问题描述】:

https://www.slideshare.net/mongodb/webinar-working-with-graph-data-in-mongodb 中所述,幻灯片 50 可以在视图上使用 $graphLookup 以获得 嵌套格式的 2 级深度树结构>.

我有一个 MongoDB 集合,其中包含树节点作为文档,格式如下:

{ "_id" : { "$oid" : "5b1a952361c6fa3418a15660" }, 
"nodeId" : 23978995, 
"name" : "settings", 
"type" : "Node",
"parentId" : [ 23978893, 23979072, 23979081 ] }

我创建了一个类似的视图:

db.createView("treeView", "node", [
{
 $graphLookup: {
    from: "node",
    startWith: "$nodeId",
    connectFromField: "nodeId",
    connectToField: "parentId",
    maxDepth: 0,
    as: "children"
 }
}
]);

然后我执行如下图查找:

db.node.aggregate([ 
{ $match: {"nodeId": 23978786 } },
{
 $graphLookup: {
    from: "treeView",
    startWith: "$nodeId",
    connectFromField: "nodeId",
    connectToField: "parentId",
    maxDepth: 0,
    as: "children"
 }
}
]);

我的问题是如何获得整个层次结构,所有层次都深?

【问题讨论】:

  • $graphLookup 不返回“嵌套格式”。您得到的输出与您看到的完全一样,并且可以选择添加一个属性来指示匹配的“找到的深度”。如果您正在寻找“无限深度”,那么应该有一个非常清楚的理由说明为什么数据库不存在。您当然可以指定 maxDepth 到您实际需要进行的深度递归。
  • @NeilLunn 请查看我提供的资源。通过创建 View 并在 View 上运行$graphLookup,实现了嵌套。我把这个付诸实践。现在,我要问的是我能否深入了解这一点。
  • 我认为这个答案是完整的答案GraphQL Hierarchy

标签: mongodb aggregation-framework tree-structure


【解决方案1】:

很遗憾,您无法以嵌套格式获得完整的深度。使用视图是一种解决方法,可让您执行该操作,但您需要为所需的每个嵌入级别创建一个新视图。 相反,我会考虑在不提供深度的情况下执行 graphLookup,从根级别开始,在单个查询中获取所有层次结构,然后在应用程序级别计算树。

这看起来像这样:

db.node.aggregate([
    { $match: {
        parentId: null
    }},
    { $graphLookup: {
        from: "node",
        startWith: "$nodeId",
        connectFromField: "nodeId",
        connectToField: "parentId",
        depthField: "depth",
        as: "children"
    }}
]);

这应该可以让您一次性获取整个层次结构,因此接下来,您需要根据“children”数组中的信息计算应用程序中的树。

【讨论】:

    【解决方案2】:

    @kmandalas 我在过去 2 天遇到了这种问题, 我的收藏有点不同,但概念和你的一样我希望我写的内容能帮助你得到结果,(我使用 SO 答案的参考)

    我的收藏架构是这样的:

    const Category = new Schema({
        sTitle: { type: String, trim: true },
        iParentId: { type: mongoose.Schema.Types.ObjectId, ref: 'Category' },
        bStatus: { type: Boolean, default: true },
        dUpdatedAt: { type: Date },
        dCreatedAt: { type: Date, default: Date.now }
    });

    首先,我使用 $graphLookup,然后将所有孩子都归入一个合适的父母,例如:

    {
      "_id": "5c6fa228c30bbf02cf12fe6c",
       "sTitle": "firstParent",
       "childrens":[{obj},{obj},{obj},{obj}]    // Childrens as well as grandChild
    },
    {
      "_id": "5c80d644ab57dd06d48cc474",
       "sTitle": "secondParent",
       "childrens":[]     //No Child
    },
    .....

    得到这种结果后,我在 node js 中创建了一个树,而不使用任何第三方库。 树的逻辑代码是 :(!note:docs is $graphlooup output nothing else)

    function list_to_tree(list) {
                var map = {}, node, roots = [], i;
                for (i = 0; i < list.length; i += 1) {
                    map[list[i]._id] = i;
                    list[i].children = [];
                }
                for (i = 0; i < list.length; i += 1) {
                    node = list[i];
                    if (node.iParentId !== null && map[node.iParentId] !== undefined) {
                        var node2 = {         //Because i need only _id,Title & childrens
                            _id: node._id,
                            Title: node.sTitle,
                            children: node.children
                        }
                        list[map[node.iParentId]].children.push(node2); //You can push direct "node"
                    } else {
                        var node2 = {
                            _id: node._id,
                            Title: node.sTitle,
                            children: node.children
                        }
                        roots.push(node2);
                    }
                }
                return roots;
            }
            let final_result = []     //For Storing all parent with childs
            if (docs.length >= 0) {   
                docs.map(single_doc => {  //For getting all parent Tree
                    var single_child = list_to_tree(single_doc.children)
                    var obj = {
                        _id: single_doc._id,
                        Title: single_doc.sTitle,
                        children: single_child
                    }
                    final_result.push(obj)
                })
            }
            console.log("Final Tree is : ",final_result)

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多