从 mongodb 中的父级获取完整树

问题描述 投票:0回答:1

我使用带有集合的 MongoDB 数据库,使用树父子引用。

集合中的每个文档都包含一个属性:parentId。parentId 属性是对父文档的 (ObjectId) 引用,它可以为 null。

样品:

[{
  "_id": {
    "$oid": "64d9f2bb7a587e250e3acb45"
  },
  "isActive": true,
  "name": "Test1"
}, {
  "_id": {
    "$oid": "64dc481d37a38cb58de04ffb"
  },
  "isActive": true,
  "name": "Test2"
}, {
  "_id": {
    "$oid": "64d9dd9f7a587e250e3ac95b"
  },
  "isActive": true,
  "name": "Test1-1",
  "parentId": {
    "$oid": "64d9f2bb7a587e250e3acb45"
  }
}, {
  "_id": {
    "$oid": "64dca02f0ff1ddfc4e40a874"
  },
  "isActive": true,
  "name": "Test1-1-1",
  "parentId": {
    "$oid": "64d9dd9f7a587e250e3ac95b"
  }
}]

我使用了

$graphLookup
,但它只获取一个列表字段中的所有子项。我需要它来填充从父级到子级的递归树结构,例如:


{
  "_id": {
    "$oid": "64d9f2bb7a587e250e3acb45"
  },
  "isActive": true,
  "name": "Test1",
  "childrents": [
    {
      "_id": {
        "$oid": "64d9dd9f7a587e250e3ac95b"
      },
      "name": "Test1-1",
      "isActive": true,
      "childrents": [
        {
            "_id": {
                "$oid": "64dca02f0ff1ddfc4e40a874"
             },
            "isActive": true,
            "name": "Test1-1-1",
            "childrents": []
        }
      ]
    }
  ]
}, {
  "_id": {
    "$oid": "64dc481d37a38cb58de04ffb"
  },
  "isActive": true,
  "name": "Test2",
  "childrents": []
}

非常感谢您的帮助,我真的很感激!

mongodb aggregation-framework graphlookup
1个回答
0
投票

经过研究,我找到了以下解决方案https://mongoplayground.net/p/Fp5LlivVzlX。谁有更好的解决方案请告诉我。谢谢

[{
 $graphLookup: {
  from: 'collection',
  startWith: '$_id',
  connectFromField: '_id',
  connectToField: 'parentId',
  as: 'childrens',
  restrictSearchWithMatch: {
   isActive: true
  },
  depthField: 'level'
 }
}, {
 $unwind: {
  path: '$childrens',
  preserveNullAndEmptyArrays: true
 }
}, {
 $sort: {
  'childrens.level': -1
 }
}, {
 $group: {
  _id: '$_id',
  parentId: {
   $first: '$parentId'
  },
  isActive: {
   $first: '$isActive'
  },
  name: {
   $first: '$name'
  },
  childrens: {
   $push: '$childrens'
  }
 }
}, {
 $addFields: {
  childrens: {
   $reduce: {
    input: '$childrens',
    initialValue: {
     level: -1,
     presentChild: [],
     prevChild: []
    },
    'in': {
     $let: {
      vars: {
       prev: {
        $cond: [
         {
          $eq: [
           '$$value.level',
           '$$this.level'
          ]
         },
         '$$value.prevChild',
         '$$value.presentChild'
        ]
       },
       current: {
        $cond: [
         {
          $eq: [
           '$$value.level',
           '$$this.level'
          ]
         },
         '$$value.presentChild',
         []
        ]
       }
      },
      'in': {
       level: '$$this.level',
       prevChild: '$$prev',
       presentChild: {
        $concatArrays: [
         '$$current',
         [
          {
           $mergeObjects: [
            '$$this',
            {
             childrens: {
              $filter: {
               input: '$$prev',
               as: 'e',
               cond: {
                $eq: [
                 '$$e.parentId',
                 '$$this._id'
                ]
               }
              }
             }
            }
           ]
          }
         ]
        ]
       }
      }
     }
    }
   }
  }
 }
}, {
 $addFields: {
  childrens: '$childrens.presentChild'
 }
}]
© www.soinside.com 2019 - 2024. All rights reserved.