Mongodb递归查询在$graphLookup中无法按预期工作

Mongodb递归查询在$graphLookup中无法按预期工作,mongodb,Mongodb,在我的文档中,我有_id、公司名称和赞助商(通过_id标识父文档) 例如,我有第一个没有赞助商(家长)的记录 然后是公司1,其中主公司为母公司: _id:607e16760a9d2c16e06bc252 companyname:"Company 1" sponsor:"607536219910ef23e80e0bbe" _id:607e187b0a9d2c16e06bc253 companyname:"Company 2&q

在我的文档中,我有_id、公司名称和赞助商(通过_id标识父文档)

例如,我有第一个没有赞助商(家长)的记录

然后是公司1,其中主公司为母公司:

  _id:607e16760a9d2c16e06bc252
    companyname:"Company 1"
    sponsor:"607536219910ef23e80e0bbe"
_id:607e187b0a9d2c16e06bc253
companyname:"Company 2"
sponsor:"607e16760a9d2c16e06bc252"
_id:607e1f470a9d2c16e06bc254
companyname:"Company 3"
sponsor:"607e187b0a9d2c16e06bc253"
以及公司2,其中公司1为母公司:

  _id:607e16760a9d2c16e06bc252
    companyname:"Company 1"
    sponsor:"607536219910ef23e80e0bbe"
_id:607e187b0a9d2c16e06bc253
companyname:"Company 2"
sponsor:"607e16760a9d2c16e06bc252"
_id:607e1f470a9d2c16e06bc254
companyname:"Company 3"
sponsor:"607e187b0a9d2c16e06bc253"
以及公司3,其中公司2为母公司:

  _id:607e16760a9d2c16e06bc252
    companyname:"Company 1"
    sponsor:"607536219910ef23e80e0bbe"
_id:607e187b0a9d2c16e06bc253
companyname:"Company 2"
sponsor:"607e16760a9d2c16e06bc252"
_id:607e1f470a9d2c16e06bc254
companyname:"Company 3"
sponsor:"607e187b0a9d2c16e06bc253"
我正在做一场$match比赛,为主要公司带来儿童唱片

{
  sponsor: '607536219910ef23e80e0bbe'
}
然后输入$addFields userid,这是一个转换为字符串的_Id。这将在以后与赞助商进行匹配:

{"userid": { "$toString": "$_id" }}
现在,当我graphLookup时,我得到了主公司的子公司(公司2),但我没有得到公司3作为公司2的子公司。我刚得到公司1和公司2:

这是我的笔录

{
  from: 'pls',
  startWith: "$userid",
  connectFromField: 'userid',
  connectToField: 'sponsor',
  as: 'downline',
  maxDepth: 100,
  restrictSearchWithMatch: {}
}
任何帮助都将不胜感激

更新:

正如Turivishal在下面所说的,查询是有效的,但我预期的结果是:

[{
        "_id": "607536219910ef23e80e0bbe",
        "companyname": "Main Company",
        "downline": [{
            "_id": "607e16760a9d2c16e06bc252",
            "companyname": "Company 1",
            "sponsor": "607536219910ef23e80e0bbe",
            "downline": [{
                "_id": "607e187b0a9d2c16e06bc253",
                "companyname": "Company 2",
                "sponsor": "607e16760a9d2c16e06bc252",
                "downline": [{
                    "_id": "607e1f470a9d2c16e06bc254",
                    "companyname": "Company 3",
                    "sponsor": "607e187b0a9d2c16e06bc253"
                }]
            }]
        }],
        "sponsor": "",
        "userId": "607536219910ef23e80e0bbe"
    }
由TURIVISHAL提供的解决方案:

根据Turivishal解决方案,这是最终的管道,它提供了循环查询的完美下线/层次结构/树视图,并与角度树视图控件完美配合。非常感谢你,图里维沙尔。我相信你应该发布一个答案,这样我可以接受它,它可以对其他人有用

他的解决方案与他提出的非常相似,但要好得多。我最终创建了一个名为PLID的新字段,它复制了_id字段,并且工作得非常好。我让管理员决定是否应该结束这个问题,因为同样,Turivishal解决方案是基于这个Q,但在我看来更清楚。以下是他的作品:

[
  {
    '$match': {
      'sponsor': '0'
    }
  }, {
    '$graphLookup': {
      'from': 'pls', 
      'startWith': '$plid', 
      'connectFromField': 'plid', 
      'connectToField': 'sponsor', 
      'depthField': 'level', 
      'as': 'children'
    }
  }, {
    '$unwind': {
      'path': '$children', 
      'preserveNullAndEmptyArrays': true
    }
  }, {
    '$sort': {
      'children.level': -1
    }
  }, {
    '$group': {
      '_id': '$plid', 
      'sponsor': {
        '$first': '$sponsor'
      }, 
      'companyname': {
        '$first': '$companyname'
      }, 
      'children': {
        '$push': '$children'
      }
    }
  }, {
    '$addFields': {
      'children': {
        '$reduce': {
          'input': '$children', 
          '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', {
                            'children': {
                              '$filter': {
                                'input': '$$prev', 
                                'as': 'e', 
                                'cond': {
                                  '$eq': [
                                    '$$e.sponsor', '$$this.plid'
                                  ]
                                }
                              }
                            }
                          }
                        ]
                      }
                    ]
                  ]
                }
              }
            }
          }
        }
      }
    }
  }, {
    '$addFields': {
      'children': '$children.presentChild'
    }
  }
]
可以使用和其他有用的数组运算符

  • $match
    只有
    赞助商的记录的过滤器是
  • $graphLookup
    获取depthField
    级别中的子记录和深度编号
  • $unwind
    解构
    下线
    数组并允许不删除空子项
  • $sort
    按深度级别字段
    级别
    降序排列
  • $group
    通过
    id
    字段并重建
    下线
    阵列
  • $addFields
    现在找到嵌套级别的子级并分配到其级别,
    • $reduce
      迭代
      下行链路的循环
    • 初始化默认字段
      level
      默认值为-1,
      presentChild
      为[],
      prevChild
      为[]以满足条件
    • $let
      初始化字段:
      • prev
        根据条件,如果两个
        level
        相等,则返回
        prevChild
        否则返回
        presentChild
      • current
        根据条件,如果两个
        级别
        相等,则返回
        presentChild
        否则[]
    • in
      返回初始化字段中的
      级别
      字段和
      prevChild
      字段
      • presentChild
        downline
        prev
        数组返回,使用
        $mergeObjects
        将当前对象与
        downline
        数组合并,使用
        $concatarray
        将let的
        数组与
        当前
        数组合并
  • $addFields
    只返回
    presentChild
    数组,因为我们只需要处理过的数组

您确定它工作正常吗?请看Hi Turivishal。谢谢你的回复。我看到了操场,这也是我得到的,但我正在寻找一个树状视图结构,其中Company2作为对象位于company1,company3作为对象位于Company2,但不显示在根级别。我在SQL Server中做过很多次,但我在将其转换为mongo db时遇到了一个真正的问题。谢谢。我不认为有任何直接的方法可以得到这个结果。请看重复的问题,我已经找到了解决方案,我已经根据您的数据更新了查询,但是您必须将
赞助商
id转换为objectId,否则此查询将无法工作。这太神奇了,Turivishal!我现在就试试看。我在S.O和谷歌上搜索了几个小时的答案,但我找不到具体的解决方案。非常感谢你!你的操场运转得很好。我最终为ID创建了一个单独的字段,并将其与赞助商合并。我尝试了您在另一个StackOverflow帖子中提供的解决方案,但没有正常工作。你的作品很有魅力。再次非常感谢你,Turivishal。