我有这样的数据:
[{ "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。 节点版本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": [...]
},]
}
我尝试了图形查找查询,
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
获取子类别记录和深度编号 defthFieldlevel
$unwind
解构数组SubCategories
并允许不删除空的子类别- 按深度级别场
level
降序$sort
- 通过
id
字段$group
并重建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
字段- 从数组
prev
presentChild
$filter
SubCategories
并返回,使用$mergeObjects
将当前对象与数组合并SubCategories
并使用$concatArrays
与 let 数组current
连接
- 从数组
$addFields
只返回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" } }
])
操场
<小时 />不含$mergeObjects
: 操场