Mongodb递归查询

fel*_*lix 9 recursion mongodb aggregation-framework

我的taxon集合中有以下架构:

{ 
  "_id": 1, 
  "na": [ "root_1",
        "root_2",
        "root_3" ], 
  "pa": 1 
},{
  "_id": 2, 
  "na": [ "name_1", 
        "name_2", 
        "name_3"], 
  "pa": 1
},{
  "_id": 4, 
  "na": [ "otherName_1", 
        "otherName_2", 
        "otherName_3"],
  "pa": 2
}
Run Code Online (Sandbox Code Playgroud)

每个文档都由父字段与另一个文档相关联,该字段对应于_id其父项.

我想执行递归搜索以获得以下结果:

{ "_id": 4, 
  "nameList": [ "otherName_1",
              "name_1",
              "root_1"]
} 
Run Code Online (Sandbox Code Playgroud)

从某个文件中_id获取na每个父项的数组的第一项,直到_id: 1达到 文档为止

我目前通过执行X查询得到这个结果(一个通过父文档,例如这里有3个),但我很确定这可以使用单个查询来实现.我已经看过新的$ graphLookup操作符了,但无法用它来解决问题...

是否可以使用MongoDB 3.4.1在单个查询中实现此目的?

编辑

我每次都会运行50个文档,因此最佳解决方案是将所有内容组合在一个查询中

例如,它看起来像

var listId = [ 4, 128, 553, 2728, ...];
var cursor = db.taxon.aggregate([
  {$match: 
     { _id: {$in: listId}}
  }, ...
)];  
Run Code Online (Sandbox Code Playgroud)

并将输出:

[{ "_id": 4, 
  "nameList": [ "otherName_1",
              "name_1",
              "root_1"]
}, { "_id": 128, 
  "nameList": [ "some_other_ame_1",
              "some_name_1",
              "root_1"]
}, { "_id": 553, 
  "nameList": [ "last_other_ame_1",
              "last_name_1",
              "root_1"]
} ... ]
Run Code Online (Sandbox Code Playgroud)

use*_*814 10

您可以尝试以下聚合.

阶段 $match - $graphLookup - $project.

$reduce从每个$graphLookup nameList's na数组中选择第一个元素.

db.taxon.aggregate([{
    $match: {
        _id: {
            $in: listId
        }
    }
}, {
    $graphLookup: {
        from: "taxon",
        startWith: "$_id",
        connectFromField: "pa",
        connectToField: "_id",
        as: "nameList"
    }
}, {
    $project: {
        nameList: {
            $reduce: {
                input: "$nameList",
                initialValue: [],
                in: {
                    "$concatArrays": ["$$value", {
                        $slice: ["$$this.na", 1]
                    }]
                }
            }
        }
    }
}])
Run Code Online (Sandbox Code Playgroud)