首页 > 解决方案 > 如何使用 MongoDB 的 $graphLookup 获取所有子节点

问题描述

我在 MongoDB 集合中有如下数据。

{ "_id" : 1, "name" : "Dev" }
{ "_id" : 2, "name" : "Eliot", "parentId" : 1 }
{ "_id" : 3, "name" : "Ron", "parentId" : 2 }
{ "_id" : 4, "name" : "Andrew", "parentId" : 2 }
{ "_id" : 5, "name" : "Asya", "parentId" : 3 }
{ "_id" : 6, "name" : "Dan", "parentId" : 4 }

我可以使用“$graphLookup”来获取孩子和父母。

db.xmantree.aggregate( [
   {
      name: "Eliot"
   },
   {
      $graphLookup: {
          from: 'xmantree',
          startWith: '$_id',
          connectFromField: 'parentId',
          connectToField: 'parentId',
          as: 'children'
       }
   },
  {
      $graphLookup: {
          from: 'xmantree',
          startWith: '$parentId',
          connectFromField: 'parentId',
          connectToField: '_id',
          as: 'parents'
       }
   }
] )

结果是这样的。

{
    _id:2,
    name: "Eliot",
    parentId: 1,
    children: [
        {
            _id: 3,
            name: "Ron",
            parentId: 2,
        },
        {
            _id: 4,
            name: "Andrew",
            parentId: 2,
        },
    ],
    parents: [
        {
            _id: 1,
            name: "Dev"
        }
    ]
}

但在这种情况下,罗恩和安德鲁每个人都有更多的孩子。所以我想通过一个聚合查询递归地得到这个。
比如这种结果。

{
    _id:2,
    name: "Eliot",
    parentId: 1,
    children: [
        {
            _id: 3,
            name: "Ron",
            parentId: 2,
            children: [...] // <- I want to get this.
        },
        {
            _id: 4,
            name: "Andrew",
            parentId: 2,
            children: [...] // <- I want to get this.
        },
    ],
    parents: [
        {
            _id: 1,
            name: "Dev"
        }
    ]
}

我的目标在 MongoDB 中是否可行?

标签: mongodbmongodb-query

解决方案


您可以$graphLookup这样设置以获得所有子节点的数组:

{
    $graphLookup: {
      from: "xmantree",
      startWith: "$_id",
      connectFromField: "_id",
      connectToField: "parentId",
      as: "children"
    }
  }

这是Mongo游乐场供您参考。

但是,对于您预期的分层输出形式,您需要知道递归级别。如果您有这些信息,您可以执行以下操作:

db.xmantree.aggregate([
  {
    "$match": {
      name: "Eliot"
    }
  },
  {
    "$lookup": {
      "from": "xmantree",
      let: {
        parentId: "$_id"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                "$$parentId",
                "$parentId"
              ]
            }
          }
        },
        {
          "$lookup": {
            "from": "xmantree",
            "localField": "_id",
            "foreignField": "parentId",
            "as": "children"
          }
        }
      ],
      "as": "children"
    }
  }
])

这是Mongo游乐场供您参考。


推荐阅读