如何获取猫鼬数据的分层嵌套对象

How to Get hierarchical nested object of mongoose data

我有这样的数据:

[{ "id": 80, "Category": "1", "sub_category": null},
 { "id": 81, "Category": "1.1", "sub_category": 80},
{ "id": 82, "Category": "1.1.1", "sub_category": 81},
{ "id": 83, "Category": "1.2", "sub_category": 80},
{ "id": 84, "Category": "1.1.1.1", "sub_category": 82}]

我正在将 Express JS 与猫鼬一起使用。 node 版本 10.19.0 和 npm 版本 6.14.9 以及 express js 版本 4.17.1。 我有一个类别 table,我必须获取具有分层嵌套数据的数据。 像这样

 { "id": 80, 
   "Category": "1", 
   "sub_category": null, 
   "SubCategories": [{ "id": 81, 
                       "Category": "1.1", 
                       "sub_category": 80,
                       "SubCategories": [{ "id": 82, 
                                            "Category": "1.1.1", 
                                            "sub_category": 81,
                                            "SubCategories": [{ "id": 84, 
                                                                "Category": "1.1.1.1", 
                                                                "sub_category": 82,
                                                                "SubCategories": [...]
                                                              },]
                                           },]
                     },
                     { "id": 83, 
                       "Category": "1.2", 
                       "sub_category": 80,
                       "SubCategories": [...]
                     },]
 }

我为此尝试了 graphLookup 查询,

CategoryModel.aggregate([{
  $graphLookup: {
    from: "examcategories", 
    startWith: "$id", 
    connectFromField: "id", 
    connectToField: "sub_category", 
    as: "SubCategoies" 
  } 
}])

并得到这样的输出

{ 
  "id": 80, 
  "Category": "1", 
  "sub_category": null,
  "SubCategories": [{ 
    "id": 81,
    "Category": "1.1",
    "sub_category": 80 
   },{ 
     "id": 82,
     "Category":"1.1.1",
     "sub_category": 81 
   },{ 
     "id": 84,
     "Category": "1.1.1.1",
     "sub_category": 82 
   },{ 
     "id": 83,
     "Category": "1.2",
     "sub_category": 80,
   }
]}

$graphLookup 对集合执行递归搜索,具有通过递归深度和查询过滤器限制搜索的选项,但仅 $groupLookup 还不够,需要使用更多运算符

  • $match 记录只有 sub_category 的过滤器是 null
  • $graphLookup获取defthField中的子类记录和深度数level
  • $unwind解构SubCategories数组并允许不删除空子类别
  • $sort按深度级别字段level降序
  • $group 通过 id 字段并重构 SubCategories 数组
CategoryModel.aggregate([
  { $match: { sub_category: null } },
  {
    $graphLookup: {
      from: "examcategories",
      startWith: "$id",
      connectFromField: "id",
      connectToField: "sub_category",
      depthField: "level",
      as: "SubCategories"
    }
  },
  {
    $unwind: {
      path: "$SubCategories",
      preserveNullAndEmptyArrays: true
    }
  },
  { $sort: { "SubCategories.level": -1 } },
  {
    $group: {
      _id: "$id",
      sub_category: { $first: "$sub_category" },
      Category: { $first: "$Category" },
      SubCategories: { $push: "$SubCategories" }
    }
  },
  • $addFields 现在找到嵌套级别的子类别并分配给它的级别,
    • $reduce 迭代 SubCategories 数组的循环。
    • 初始化默认字段level默认值为-1,presentChild为[],prevChild为[]用于条件目的
    • $let 初始化字段:
      • prev 根据条件如果两个 level 相等则 return prevChild 否则 return presentChild
      • current 根据条件如果两个 level 相等则 return presentChild 否则 []
    • in 到 return level 字段和初始化字段中的 prevChild 字段
      • presentChild $filter SubCategories 来自 prev 数组和 return,使用 $mergeObjects 将当前对象与 SubCategories 数组合并并使用 $concatArrays
      • 与 let 的 current 数组连接
  • $addFields 到 return 只有 presentChild 数组,因为我们只需要处理过的数组
  {
    $addFields: {
      SubCategories: {
        $reduce: {
          input: "$SubCategories",
          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",
                          {
                            SubCategories: {
                              $filter: {
                                input: "$$prev",
                                as: "e",
                                cond: { $eq: ["$$e.sub_category", "$$this.id"] }
                              }
                            }
                          }
                        ]
                      }
                    ]
                  ]
                }
              }
            }
          }
        }
      }
    }
  },
  { $addFields: { SubCategories: "$SubCategories.presentChild" } }
])

Playground


没有$mergeObjectsPlayground