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

时间:2020-12-22 12:09:01

标签: node.js mongodb express categories

我有这样的数据:

[{ "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。 我有一个类别表,我必须使用分层嵌套数据获取数据。 像这样

 { "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,
   }
]}

1 个答案:

答案 0 :(得分:0)

$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 相等则返回 prevChild 否则返回 presentChild
      • current 根据条件,如果两个 level 相等则返回 presentChild 否则返回 []
    • in 从初始化字段返回 level 字段和 prevChild 字段
      • presentChild $filter SubCategories 来自 prev 数组并返回,使用 SubCategories 将当前对象与 $mergeObjects 数组合并,并使用 {{1} 连接}} let 数组使用 current
  • $concatArrays 只返回 $addFields 数组,因为我们只需要处理过的数组
presentChild

Playground


没有 { $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