MongoDB的$ graphLookup。处理具有多个父项和多个子项的节点

时间:2017-01-24 22:11:42

标签: mongodb graph

我正在尝试使用新的MongoDB v3.4 $ graphLookup聚合管道元素。我有数据“节点”,可以有0,1或多个父节点。每个节点还可以具有0,1或多个子节点。我想使用$ graphLookup来产生以下输出:

 {"parentNodeKey":  undefined, "parentLabel": undefined, "nodeKey": 1, "nodeLabel": "Node 1"},
 {"parentNodeKey":  1, "parentLabel": "Node 1", "nodeKey": 11, "nodeLabel": "Node 1.1"},
 {"parentNodeKey":  1, "parentLabel": "Node 1", "nodeKey": 12, "nodeLabel": "Node 1.2"},
 {"parentNodeKey":  1, "parentLabel": "Node 1", "nodeKey": 13, "nodeLabel": "Node 1.3"},
 {"parentNodeKey":  1, "parentLabel": "Node 1", "nodeKey": 31, "nodeLabel": "Node 3.1"},
 {"parentNodeKey": 11, "parentLabel": "Node 1.1", "nodeKey": 111, "nodeLabel": "Node 1.1.1"},
 {"parentNodeKey": 11, "parentLabel": "Node 1.1", "nodeKey": 112, "nodeLabel": "Node 1.1.2"},
 {"parentNodeKey": 12, "parentLabel": "Node 1.2", "nodeKey": 121, "nodeLabel": "Node 1.2.1"},
 {"parentNodeKey": 12, "parentLabel": "Node 1.2", "nodeKey": 122, "nodeLabel": "Node 1.2.2"}

数据存储在以下模式中(如有必要,我可以更改):

{"_id":   1, "nodeKey":  1, "label": "Node 1", "children": [{"nodeKey": 11, "label": "Node 1.1"}
                                                        ,{"nodeKey": 12, "label": "Node 1.2"}
                                                        ,{"nodeKey": 13, "label": "Node 1.3"}
                                                        ,{"nodeKey": 31, "label": "Node 3.1"}
                                                        ]},
{"_id":   2, "nodeKey":  2, "label": "Node 2", "children": [{"nodeKey": 21, "label": "Node 2.1"}
                                                        ,{"nodeKey": 22, "label": "Node 2.2"}
                                                        ,{"nodeKey": 23, "label": "Node 2.3"}
                                                        ,{"nodeKey": 12, "label": "Node 1.2"}
                                                        ,{"nodeKey": 31, "label": "Node 3.1"}
                                                        ]},
{"_id":   3, "nodeKey":  3, "label": "Node 3", "children": [{"nodeKey": 31, "label": "Node 3.1"}
                                                        ,{"nodeKey": 32, "label": "Node 3.2"}
                                                        ,{"nodeKey": 33, "label": "Node 3.3"}
                                                        ,{"nodeKey": 11, "label": "Node 1.1"}
                                                        ]},
{"_id":  11, "nodeKey": 11, "label": "Node 1.1", "children": [{"nodeKey": 111, "label": "Node 1.1.1"}
                                                          ,{"nodeKey": 112, "label": "Node 1.1.2"}
                                                          ]
                                            , "parents": [{"nodeKey": 1, "label": "Node 1"}
                                                         ,{"nodeKey": 3, "label": "Node 3"}
                                                         ]},
{"_id":  12, "nodeKey": 12, "label": "Node 1.2", "children": [{"nodeKey": 121, "label": "Node 1.2.1"}
                                                          ,{"nodeKey": 122, "label": "Node 1.2.2"}
                                                          ]
                                            , "parents": [{"nodeKey": 1, "label": "Node 1"}
                                                         ,{"nodeKey": 2, "label": "Node 2"}
                                                         ]},
{"_id":  13, "nodeKey": 13, "label": "Node 1.3", "parents": [{"nodeKey": 1, "label": "Node 1"}]},
{"_id":  21, "nodeKey": 21, "label": "Node 2.1", "parents": [{"nodeKey": 2, "label": "Node 2"}]},
{"_id":  22, "nodeKey": 22, "label": "Node 2.2", "parents": [{"nodeKey": 2, "label": "Node 2"}]},
{"_id":  23, "nodeKey": 23, "label": "Node 2.3", "parents": [{"nodeKey": 2, "label": "Node 2"}]},
{"_id":  31, "nodeKey": 31, "label": "Node 3.1", "parents": [{"nodeKey": 1, "label": "Node 1"}
                                                         ,{"nodeKey": 2, "label": "Node 2"}
                                                         ,{"nodeKey": 3, "label": "Node 3"}]},
{"_id":  32, "nodeKey":  32, "label": "Node 3.2", "parents": [{"nodeKey": 3, "label": "Node 3"}]},
{"_id":  33, "nodeKey":  33, "label": "Node 3.3", "parents": [{"nodeKey": 3, "label": "Node 3"}]},
{"_id": 111, "nodeKey": 111, "label": "Node 1.1.1", "parents": [{"nodeKey": 11, "label": "Node 1.1"}]},
{"_id": 112, "nodeKey": 112, "label": "Node 1.1.2", "parents": [{"nodeKey": 11, "label": "Node 1.1"}]},
{"_id": 121, "nodeKey": 121, "label": "Node 1.2.1", "parents": [{"nodeKey": 12, "label": "Node 1.2"}]},
{"_id": 122, "nodeKey": 122, "label": "Node 1.2.2", "parents": [{"nodeKey": 12, "label": "Node 1.2"}]}

$ graphLookup似乎没有提供有关节点的直接父节点的任何信息。我使用了以下聚合管道,但未成功:

db.nodes.aggregate(
[{$match: {"nodeKey": 1}
 }
,{$graphLookup : {
    from            : "nodes",
    startWith       : "$children.nodeKey",
    connectFromField: "children.nodeKey",
    connectToField  : "nodeKey",
    maxDepth        : 5,
    depthField      : "depth",
    as              : "child"}
 }
,{
     $project: {
          "_id"           : 0
         ,"nodeKey"       : 1
         ,"child.depth"   : 1
         ,"child.nodeKey" : 1
         ,"child.label"   : 1
     }
  }
]).pretty()

我正在寻找任何建议。感谢。

1 个答案:

答案 0 :(得分:1)

您需要将收藏文档结构更改为引用nodekey'schildren数组中的parents

像这样的东西

{"_id":  12, "nodeKey": 12, "label": "Node 1.2", "children": [121, 122], "parents": [1, 2]}

使用以下聚合查询。

这可以帮助你开始。我会让你使用它来获得你想要的输出。

重要的是要注意我们几次使用$graphLookup次。第一次查找将为您提供childs,接下来将为您提供parents给孩子。

db.nodes.aggregate([
     {$match: {"nodeKey": 1}},
     {$graphLookup : {
        from            : "nodes",
        startWith       : "$children",
        connectFromField: "children",
        connectToField  : "nodeKey",
        maxDepth        : 5,
        as              : "child"}
     },
     {$unwind:"$child"},
     {$replaceRoot:{newRoot:"$child"}},
     {$graphLookup : {
        from            : "nodes",
        startWith       : "$parents",
        connectFromField: "parents",
        connectToField  : "nodeKey",
        maxDepth        : 5,
        as              : "parent"
        }
     },
     {$project: {
         _id           : 0,
         parentNodeKey : "$parent.nodeKey",
         parentLabel   : "$parent.label",
         nodeLabel     : "$label",
         nodeKey       : 1
         }
     }
]);

首次查找后的输出

{ "_id" : 121, "nodeKey" : 121, "label" : "Node 1.2.1", "parents" : [ 12 ] }
{ "_id" : 112, "nodeKey" : 112, "label" : "Node 1.1.2", "parents" : [ 11 ] }
{ "_id" : 122, "nodeKey" : 122, "label" : "Node 1.2.2", "parents" : [ 12 ] }
{ "_id" : 31, "nodeKey" : 31, "label" : "Node 3.1", "parents" : [ 1, 2, 3 ] }
{ "_id" : 12, "nodeKey" : 12, "label" : "Node 1.2", "children" : [ 121, 122 ], "parents" : [ 1, 2 ] }
{ "_id" : 111, "nodeKey" : 111, "label" : "Node 1.1.1", "parents" : [ 11 ] }
{ "_id" : 13, "nodeKey" : 13, "label" : "Node 1.3", "parents" : [ 1 ] }
{ "_id" : 11, "nodeKey" : 11, "label" : "Node 1.1", "children" : [ 111, 112 ], "parents" : [ 1, 3 ] }

最终输出

{ "nodeKey" : 121, "parentNodeKey" : [ 1, 2, 12 ], "parentLabel" : [ "Node 1", "Node 2", "Node 1.2" ], "nodeLabel" : "Node 1.2.1" }
{ "nodeKey" : 112, "parentNodeKey" : [ 1, 3, 11 ], "parentLabel" : [ "Node 1", "Node 3", "Node 1.1" ], "nodeLabel" : "Node 1.1.2" }
{ "nodeKey" : 122, "parentNodeKey" : [ 1, 2, 12 ], "parentLabel" : [ "Node 1", "Node 2", "Node 1.2" ], "nodeLabel" : "Node 1.2.2" }
{ "nodeKey" : 31, "parentNodeKey" : [ 3, 2, 1 ], "parentLabel" : [ "Node 3", "Node 2", "Node 1" ], "nodeLabel" : "Node 3.1" }
{ "nodeKey" : 12, "parentNodeKey" : [ 2, 1 ], "parentLabel" : [ "Node 2", "Node 1" ], "nodeLabel" : "Node 1.2" }
{ "nodeKey" : 111, "parentNodeKey" : [ 1, 3, 11 ], "parentLabel" : [ "Node 1", "Node 3", "Node 1.1" ], "nodeLabel" : "Node 1.1.1" }
{ "nodeKey" : 13, "parentNodeKey" : [ 1 ], "parentLabel" : [ "Node 1" ], "nodeLabel" : "Node 1.3" }
{ "nodeKey" : 11, "parentNodeKey" : [ 3, 1 ], "parentLabel" : [ "Node 3", "Node 1" ], "nodeLabel" : "Node 1.1" }