作者:余陈辉syllabear | 来源:互联网 | 2023-02-01 19:40
我正在尝试使用新的MongoDB v3.4 $ graphLookup聚合管道.我有这个简单的树集合,有一些节点和一个父DBRef:
{ "_id" : ObjectId("59380657bbdbfb36c18a80f2"), "name" : "Root node 1" },
{ "_id" : ObjectId("5938068abbdbfb36c18a80f5"), "name" : "Child 1.1", "parent" : ObjectId("59380657bbdbfb36c18a80f2") },
{ "_id" : ObjectId("593806b0bbdbfb36c18a80f7"), "name" : "Subchild 1.1.1", "parent" : ObjectId("5938068abbdbfb36c18a80f5") },
{ "_id" : ObjectId("5938068abbdbfb36c18a80f6"), "name" : "Child 1.2", "parent" : ObjectId("59380657bbdbfb36c18a80f2") },
{ "_id" : ObjectId("59380657bbdbfb36c18a80f3"), "name" : "Root node 2" }
我想得到这种树形结构:
- Root node 1
- Child 1.1
- Subchild 1.1.1
- Child 1.2
- Root node 2
所以,我正在尝试使用新的$ graphLookup聚合管道,如下所示:
db.getCollection('tree').aggregate([
{ $match: { parent: { $exists: false } } },
{
$graphLookup: {
from: "tree",
startWith: "$_id",
connectFromField: "_id",
connectToField: "parent",
as: "children"
}
},
{ $sort: { name: 1 } }
])
但我的问题是我在一个集合中得到了"Root node 1"的所有孩子:
{
"_id" : ObjectId("59380657bbdbfb36c18a80f2"),
"name" : "Root node 1",
"children" : [
{ "_id" : ObjectId("593806b0bbdbfb36c18a80f7"), "name" : "Subchild 1.1.1", "parent" : ObjectId("5938068abbdbfb36c18a80f5") },
{ "_id" : ObjectId("5938068abbdbfb36c18a80f6"), "name" : "Child 1.2", "parent" : ObjectId("59380657bbdbfb36c18a80f2") },
{ "_id" : ObjectId("5938068abbdbfb36c18a80f5"), "name" : "Child 1.1", "parent" : ObjectId("59380657bbdbfb36c18a80f2") }
]
},
{
"_id" : ObjectId("59380657bbdbfb36c18a80f3"),
"name" : "Root node 2",
"children" : [ ]
}
我不知道如何递归地查找子项以获得"子1.1"的子集合中的"Subchild 1.1.1".我正在寻找任何建议.谢谢 :)
1> Sergey Berez..:
$ graphLookup不生成依赖关系的层次结构 - 它对连接的文档执行递归搜索,但结果被展平为单维数组.以下是文档中的引用:
对于每个匹配的文档,$ graphLookup获取_id的值
并检查树集合中的每个文档以获得匹配的父值.对于每个匹配,$ graphLookup将from集合中的匹配文档添加到数组子节点.此步骤以递归方式继续,直到找不到更多匹配的文档,或者直到操作达到maxDepth参数指定的递归深度.
即它以递归方式搜索依赖文档,但无论子项的位置有多深,每个找到的文档都会添加到父文档的相同子数组中.
注意 - 您没有看到Child 1.1
它已连接,Subchild 1.1.1
因为您在match
阶段过滤掉这些文档:
{ $match: { parent: { $exists: false } } }
只选择没有父母的文件 - "Root node 1"
和"Root node 2"
.如果要删除此过滤器,则将返回具有其依赖项层次结构的所有其他文档:
{
"name" : "Child 1.1",
"children" : [
{ "name" : "Subchild 1.1.1" }
]
},
{
"name" : "Child 1.2"
"children" : []
},
{
"name" : "Root node 1",
"children" : [
{ "name" : "Subchild 1.1.1" },
{ "name" : "Child 1.2" },
{ "name" : "Child 1.1" }
]
},
{
"name" : "Root node 2",
"children" : []
},
{
"name" : "Subchild 1.1.1"
"children" : []
}
如果您不想在单个子数组中混合来自不同"深度"树的子项,那么请查看文档中的有趣注释
将maxDepth字段设置为0等同于非递归$ lookup搜索阶段.
这意味着每个文档都会将其所有直接子项都放入子数组中,然后查找将停止而不进行任何进一步的递归搜索.输出将是
{
"name" : "Child 1.1",
"children" : [
{ "name" : "Subchild 1.1.1" }
]
},
{
"name" : "Child 1.2"
"children" : []
},
{
"name" : "Root node 1",
"children" : [
{ "name" : "Child 1.2" },
{ "name" : "Child 1.1" }
]
},
{
"name" : "Root node 2",
"children" : []
},
{
"name" : "Subchild 1.1.1"
"children" : []
}