Javascript 从物化路径创建特定的树结构
我有实体和实体模板。顶级实体绑定到一个实体模板,即templateId1。从那里,一个实体通过使用其id绑定到路径中的另一个实体。我试图以一种高效的方式结束以下数据结构:Javascript 从物化路径创建特定的树结构,javascript,arrays,mongodb,materialized-path-pattern,Javascript,Arrays,Mongodb,Materialized Path Pattern,我有实体和实体模板。顶级实体绑定到一个实体模板,即templateId1。从那里,一个实体通过使用其id绑定到路径中的另一个实体。我试图以一种高效的方式结束以下数据结构: const entities = [ { id: 'xi32', name: 'Some name', path: ',templateId1,' }, { id: 'x382', name: 'Some name 2', path: ',templateId1,xi
const entities = [
{
id: 'xi32',
name: 'Some name',
path: ',templateId1,'
},
{
id: 'x382',
name: 'Some name 2',
path: ',templateId1,xi32,'
},
{
id: '2oxwo',
name: 'Some name 3',
path: ',templateId1,xi32,x382,'
},
{
id: '2',
name: '2',
path: ',templateId1,'
},
{
id: '2-2',
name: '2-2',
path: ',templateId1,2,'
},
{
id: '3-3',
name: '3-3',
path: ',templateId1,3,'
},
{
id: '3-3-3',
name: '3-3-3',
path: ',templateId1,3,3-3,'
},
{
id: '3-3-3-3',
name: '3-3-3-3',
path: ',templateId1,3,3-3,3-3-3,'
},
{
id: '3',
name: '3',
path: ',templateId1,'
}
];
const desiredResult = [
{
id: 'xi32',
name: 'Some name',
path: ',templateId1,',
children: [
{
id: 'x382',
name: 'Some name 2',
path: ',templateId1,xi32,',
children: [
{
id: '2oxwo',
name: 'Some name 3',
path: ',templateId1,xi32,x382,',
children: null
}
]
}
]
},
{
id: '2',
name: '2',
path: ',templateId1,',
children: [
{
id: '2-2',
name: '2-2',
path: ',templateId1,2,',
children: null
}
]
},
{
id: '3',
name: '3',
path: ',templateId1,',
children: [
{
id: '3-3',
name: '3-3',
path: ',templateId1,3,',
children: [
{
id: '3-3-3',
name: '3-3-3',
path: ',templateId1,3,3-3,',
children: [
{
id: '3-3-3-3',
name: '3-3-3-3',
path: ',templateId1,3,3-3,3-3-3,',
children: null
}
]
}
]
}
]
}
];
该结构的最初灵感来自MongoDB文档:
我有一个稍微不同的用例,实体模板是顶层父级,但在实体中,用例是相同的。非常感谢您的任何见解。我已经做到了。。。
我添加了一种防止任何键紊乱的排序
常数数据=
[{id:'1',name:'1',path:',templateId1',}
,{id:'2',名称:'2',路径:',templateId1',}
,{id:'2-1',名称:'2-1',路径:',templateId1,2',}
,{id:'1-1',名称:'1-1',路径:',templateId1,1',}
,{id:'1-1-1',名称:'1-1-1',路径:',templateId1,1,1-1',}
]
让结果=[]
,parents=[{children:result}]
;
对于data.sorta的let elData,b=>a.id.localeCompareb.id
{
让newEl={…elData,children:null}
,level=elData.id.match/-/g | |长度//计数'-'的数量
;
如果父级[级别]。子级===null
{parents[level]。children=[]}
父级[级别].children.push newEl
父母[++level]=newEl
}
console.logJSON.stringifyresult,0,2//用于测试
.作为控制台包装{max height:100%!important;top:0;}我已完成此操作。。。
我添加了一种防止任何键紊乱的排序
常数数据=
[{id:'1',name:'1',path:',templateId1',}
,{id:'2',名称:'2',路径:',templateId1',}
,{id:'2-1',名称:'2-1',路径:',templateId1,2',}
,{id:'1-1',名称:'1-1',路径:',templateId1,1',}
,{id:'1-1-1',名称:'1-1-1',路径:',templateId1,1,1-1',}
]
让结果=[]
,parents=[{children:result}]
;
对于data.sorta的let elData,b=>a.id.localeCompareb.id
{
让newEl={…elData,children:null}
,level=elData.id.match/-/g | |长度//计数'-'的数量
;
如果父级[级别]。子级===null
{parents[level]。children=[]}
父级[级别].children.push newEl
父母[++level]=newEl
}
console.logJSON.stringifyresult,0,2//用于测试
.作为控制台包装{max height:100%!important;top:0;}最后,我通过大量调试成功地编写了此代码,因为有很多陷阱 其思想是将json分几次传递,每次计算剩余元素的数量 如果从一个过程到另一个过程,此数字没有减少,则pgm发送错误并停止 对于要添加的每个元素,我们计算假定的父getParentKey,它返回其所有父元素列表的表 然后必须使用此列表在表中找到直接父元素,从根开始,如果父元素不存在,则该元素将保留在表中,并将在下一步重试 常量实体= [{id:'xi32',name:'Some name',path:',templateId1',} ,{id:'x382',name:'Some name 2',path:',templateId1,xi32',} ,{id:'2oxwo',name:'Some name 3',path:',templateId1,xi32,x382',} ,{id:'2',名称:'2',路径:',templateId1',} ,{id:'2-2',名称:'2-2',路径:',templateId1,2',} ,{id:'3-3',名称:'3-3',路径:',templateId1,3',} ,{id:'3-3-3',名称:'3-3-3',路径:',templateId1,3,3-3',} ,{id:'3-3-3',名称:'3-3-3',路径:',templateId1,3,3-3,3-3',} ,{id:'3',name:'3',path:',templateId1',} ]; 常量结果=[] ; 撤消=[] ,source=实体 ; 设cpt=0//仅用于在出错时停止无限循环 ; 做 { unDone=setResult源,unDone.length 来源=未完成; 如果++cpt>10抛出“切碎!丹麦州有东西腐烂了…” } 虽然 撤消。长度>0 ; /* ----------------------------*/ console.log'result==',JSON.stringifyResult,0,2 /* ----------------------------*/ 函数setResult arrayIn,nb_rej { 让孤儿=[]; 为了阿拉因的艾尔达 { 让newEl={…elData,children:null} ,parAr=getParentKeyelData.path 如果平行长度===0 {Result.pushnewEl} 其他的 { 让resParent=结果; 做 { 让rech=parAr.pop ,fPar=resParent.findtreeElm=>treeElm.id==rech.id&&treeElm.path==rech.path ; 如果fPar { 如果fPar.children==null fPar.children=[] ; resParent=fPar.children } else//throw`parent element not found:id:'${rech.id}',path:'${rech.path}`; { orp 汉斯·普什{……埃尔达塔} resParent=null 平行长度=0 } } 虽然 平行长度>0 ; 如果resParent不是resParent.pushnewEl; } } 如果孤立.length>0&&olivers.length==nb_rej 抛出没有父元素的${nb_rej}子元素!'; 遣返孤儿 } 函数getParentKey路径 {//返回父元素的数组 让rep=[] PAR=路径 ,lev,bKey,xCom,idK; 做 { BKEY=PAR.SUBALIGIN 0,PAL.LASTENTROXOF','//移除最后一个'' lev=bKey.match/,/g.length-1 如果lev>0 { xCom=bKey.lastIndexOf',' PAR= BKEY子串0,XCOM+, idK=bKey.substring++xCom rep.push{path:par,id:idK} } } 虽然 列夫>0 退货代表 }
.作为控制台包装{max height:100%!important;top:0;}最后,我通过大量调试成功地编写了此代码,因为有很多陷阱 其思想是将json分几次传递,每次计算剩余元素的数量 如果从一个过程到另一个过程,此数字没有减少,则pgm发送错误并停止 对于要添加的每个元素,我们计算假定的父getParentKey,它返回其所有父元素列表的表 然后必须使用此列表在表中找到直接父元素,从根开始,如果父元素不存在,则该元素将保留在表中,并将在下一步重试 常量实体= [{id:'xi32',name:'Some name',path:',templateId1',} ,{id:'x382',name:'Some name 2',path:',templateId1,xi32',} ,{id:'2oxwo',name:'Some name 3',path:',templateId1,xi32,x382',} ,{id:'2',名称:'2',路径:',templateId1',} ,{id:'2-2',名称:'2-2',路径:',templateId1,2',} ,{id:'3-3',名称:'3-3',路径:',templateId1,3',} ,{id:'3-3-3',名称:'3-3-3',路径:',templateId1,3,3-3',} ,{id:'3-3-3',名称:'3-3-3',路径:',templateId1,3,3-3,3-3',} ,{id:'3',name:'3',path:',templateId1',} ]; 常量结果=[] ; 撤消=[] ,source=实体 ; 设cpt=0//仅用于在出错时停止无限循环 ; 做 { unDone=setResult源,unDone.length 来源=未完成; 如果++cpt>10抛出“切碎!丹麦州有东西腐烂了…” } 虽然 撤消。长度>0 ; /* ----------------------------*/ console.log'result==',JSON.stringifyResult,0,2 /* ----------------------------*/ 函数setResult arrayIn,nb_rej { 让孤儿=[]; 为了阿拉因的艾尔达 { 让newEl={…elData,children:null} ,parAr=getParentKeyelData.path 如果平行长度===0 {Result.pushnewEl} 其他的 { 让resParent=结果; 做 { 让rech=parAr.pop ,fPar=resParent.findtreeElm=>treeElm.id==rech.id&&treeElm.path==rech.path ; 如果fPar { 如果fPar.children==null fPar.children=[] ; resParent=fPar.children } else//throw`parent element not found:id:'${rech.id}',path:'${rech.path}`; { 孤儿。推{…elData} resParent=null 平行长度=0 } } 虽然 平行长度>0 ; 如果resParent不是resParent.pushnewEl; } } 如果孤立.length>0&&olivers.length==nb_rej 抛出没有父元素的${nb_rej}子元素!'; 遣返孤儿 } 函数getParentKey路径 {//返回父元素的数组 让rep=[] PAR=路径 ,lev,bKey,xCom,idK; 做 { BKEY=PAR.SUBALIGIN 0,PAL.LASTENTROXOF','//移除最后一个'' lev=bKey.match/,/g.length-1 如果lev>0 { xCom=bKey.lastIndexOf',' PAR= BKEY子串0,XCOM+, idK=bKey.substring++xCom rep.push{path:par,id:idK} } } 虽然 列夫>0 退货代表 }
.作为控制台包装器{max height:100%!important;top:0;}您希望在MongoDB或JavaScript中实现这一点吗?@mickl老实说,我不确定。如果可以的话,我喜欢在DB级别做一些事情,因为它通常性能更高,但特别是在这两种情况下都能做会更好。这样API就可以在需要时直接返回,树也可以用代码创建。@MisterJojo我尝试过使用它,但它采用了不同的结构,老实说,我很难解析其中的内容。我还在玩弄那个密码。@Jojo先生,我的错,那是个错误。我会编辑它。@MisterJojo我想可以,但我已经按路径排序了,所以最短路径排在第一位。假设它可以以任何顺序出现,那就太好了。我正在整理
在代码中只是为了安全。这是你想在MongoDB或JavaScript中实现的吗?@mickl老实说,我不确定。如果可以的话,我喜欢在DB级别做一些事情,因为它通常性能更高,但特别是在这两种情况下都能做会更好。这样API就可以在需要时直接返回,树也可以用代码创建。@MisterJojo我尝试过使用它,但它采用了不同的结构,老实说,我很难解析其中的内容。我还在玩弄那个密码。@Jojo先生,我的错,那是个错误。我会编辑它。@MisterJojo我想可以,但我已经按路径排序了,所以最短路径排在第一位。假设它可以以任何顺序出现,那就太好了。为了安全起见,我正在用代码对它重新排序。这看起来很棒。比我现在拥有的要短得多。需要稍微调整一下,因为关系/深度不是基于id或-,而是基于路径。我现在正在摆弄它。它应该是level=elData.path.match/,/g | |长度-2;2是为了摆脱,在弦的开始和结束。是的,男人工作得很好!通过了测试和我在评论中所做的更改。非常感谢:。我将完成我的解决方案,我也会发布它,但我喜欢你的。是的,这是我能看到的使它工作的唯一方法。身份证可以是任何东西。我只是用-作为例子。我的真实身份证是5e4dcc5e8b660466ca1fe916。因此,我们无法从id中找到任何可靠的深度/级别度量,这就是您试图达到的目的,对吗?这看起来很棒。比我现在拥有的要短得多。需要稍微调整一下,因为关系/深度不是基于id或-,而是基于路径。我现在正在摆弄它。它应该是level=elData.path.match/,/g | |长度-2;2是为了摆脱,在弦的开始和结束。是的,男人工作得很好!通过了测试和我在评论中所做的更改。非常感谢:。我将完成我的解决方案,我也会发布它,但我喜欢你的。是的,这是我能看到的使它工作的唯一方法。身份证可以是任何东西。我只是用-作为例子。我的真实身份证是5e4dcc5e8b660466ca1fe916。因此,我们无法从id中找到任何可靠的深度/级别度量,这就是您试图达到的目的,对吗?这太棒了!谢谢您:。我正在通读并试图理解代码,但它通过了所有测试。我也有一个解决方案,但我一直在和孩子们一起更新树。我可能也会把它写完,然后把它贴出来,但这很管用,所以可能不行。再次感谢!这太棒了!谢谢您:。我正在通读并试图理解代码,但它通过了所有测试。我也有一个解决方案,但我一直在和孩子们一起更新树。我可能也会把它写完,然后把它贴出来,但这很管用,所以可能不行。再次感谢!