javascript - Mongodb $graphLookup 构建层次结构
问题描述
我有一个来自 mongodb$graphLookup
聚合的输出:
db.getCollection('projects').aggregate([
{
$lookup: {
from: "projects",
localField: "_id",
foreignField: "parent",
as: "childrens"
}
}
])
{
"_id" : "1",
"name" : "Project1",
"parent" : null,
"childrens" : [
{
"_id" : "3",
"name" : "ProjectForId1",
"parent" : "1"
}
]
},
{
"_id" : "3",
"name" : "ProjectForId1",
"parent" : "1",
"childrens" : [
{
"_id" : "6",
"name" : "ProjectForId3",
"parent" : "3"
},
{
"_id" : "7",
"name" : "ProjectForId3",
"parent" : "3"
}
]
}
我需要在 javascript 中从此输出构建层次结构,或者是否可以直接从查询中构建层次结构,因此最终输出应如下所示:
{
"_id" : "1",
"name" : "Project1",
"parent" : null,
"childrens" : [
{
"_id" : "3",
"name" : "ProjectForId1",
"parent" : "1",
"childrens" : [
{
"_id" : "6",
"name" : "ProjectForId3",
"parent" : "3"
},
{
"_id" : "7",
"name" : "ProjectForId3",
"parent" : "3"
}
]
}
]
}
此外,如果有人有勇气在另一种情况下提供帮助,通过过滤 _id 创建层次结构:
例如:_id = "1"
输出将与上面相同,但_id
最终3
输出应如下所示:
{
"_id" : "3",
"name" : "ProjectForId1",
"parent" : "1",
"childrens" : [
{
"_id" : "6",
"name" : "ProjectForId3",
"parent" : "3"
},
{
"_id" : "7",
"name" : "ProjectForId3",
"parent" : "3"
}
]
}
解决方案
以下解决方案与我过去的答案之一或多或少相同,因此您可以在此处获得详尽的解释
db.projects.aggregate([
{
$graphLookup: {
from: "projects",
startWith: "$_id",
connectFromField: "_id",
connectToField: "parent",
as: "children",
maxDepth: 4,
depthField: "level"
}
},
{
$unwind: "$children"
},
{
$sort: { "children.level": -1 }
},
{
$group: {
_id: "$_id",
children: { $push: "$children" }
}
},
{
$addFields: {
children: {
$reduce: {
input: "$children",
initialValue: {
currentLevel: -1,
currentLevelProjects: [],
previousLevelProjects: []
},
in: {
$let: {
vars: {
prev: {
$cond: [
{ $eq: [ "$$value.currentLevel", "$$this.level" ] },
"$$value.previousLevelProjects",
"$$value.currentLevelProjects"
]
},
current: {
$cond: [
{ $eq: [ "$$value.currentLevel", "$$this.level" ] },
"$$value.currentLevelProjects",
[]
]
}
},
in: {
currentLevel: "$$this.level",
previousLevelProjects: "$$prev",
currentLevelProjects: {
$concatArrays: [
"$$current",
[
{ $mergeObjects: [
"$$this",
{ children: { $filter: { input: "$$prev", as: "e", cond: { $eq: [ "$$e.parent", "$$this._id" ] } } } }
] }
]
]
}
}
}
}
}
}
}
},
{
$addFields: { children: "$children.currentLevelProjects" }
},
{
$match: {
_id: "1"
}
}
])
最后阶段应该是过滤,因此您可以在此处获取任何深度级别的数据。
推荐阅读
- r - 在这种特殊情况下如何使用 read_table 或 fread ?
- flutter - 有没有办法知道 Flutter 中哪个位置文本溢出?
- ios - 在 UITableViewCell 内的 TagViews 中执行操作
- javascript - 如何根据 Tabulator 中的选定选项卡设置列
- android - 我的应用程序不断停止。这是一个基本的登录页面。附上Logcat代码
- azure - 如何在 Azure 上暴露于我的服务之外?
- android - google playstore的apk名称
- asp.net-core - 在 Razor 视图上填充字段
- postgresql - 使用 dpage/pgadmin4 映像运行 docker-compose up 时获取权限异常
- javascript - 我正在从数据库中获取表数据并显示在表上,但数据表搜索不适用于数据