Javascript 在递归节点函数中从Mongoose检索树数据
我试图在Node Express应用程序中使用Mongoose递归地从Mongodb检索树格式的数据。我试图用承诺来做这件事,但我显然做得不对 假设您拥有mongodb表Javascript 在递归节点函数中从Mongoose检索树数据,javascript,node.js,mongodb,express,tree,Javascript,Node.js,Mongodb,Express,Tree,我试图在Node Express应用程序中使用Mongoose递归地从Mongodb检索树格式的数据。我试图用承诺来做这件事,但我显然做得不对 假设您拥有mongodb表foos”: { "_id": { "$oid": "5b5fb27232db7b13a1090577" }, "bazs": [ { "$oid": "5b626a2e325c181bdf4fba08" } ], "
foos
”:
{
"_id": {
"$oid": "5b5fb27232db7b13a1090577"
},
"bazs": [
{
"$oid": "5b626a2e325c181bdf4fba08"
}
],
"bars": [
{
"$oid": "5b5fb3cc32db7b13a1090579"
}
],
"name": "Parent1",
"accountId": "5b5fb27132db7b13a1090576",
"__v": 0
}
这有两种不同的子对象。此外,baz
对象还有其他baz
对象作为子对象,以及bar
对象。假设这是条的id所对应的表:
{
"_id": {
"$oid": "5b626a2e325c181bdf4fba08"
},
"bazs": [
{
"$oid": "5b5fb3cc32db7b75fa01"
}
],
"bars": [
{
"$oid": "5b5fb3c7cdaf740a500a"
}
],
"accountId": "5b5fb27132db7b13a1090576",
"parent": {
"$oid": "5b5fb27232db7b13a1090577"
},
"__v": 0
}
我一直在使用递归函数,等待使用Mongoose检索对象类型
const getObjectRecursive = (type, id)=>{ //'type' will be 'Foo' or 'Bar'
return new Promise((resolve, reject)=>{
type.findOne.call(type, {_id:id},{}, err=>{
if(err){
reject(err);
}
})
.then((rslt)=>{
const result = rslt;
const bars = result.bars;
const bazs = result.bazs;
result.children = {};
result.children.bars = tasks.map(async barId=>{
const barIdString = barId.toString();
await getBarRecursive(barIdString, err=>{
if(err){
reject(err);
}
});
});
result.children.bazs = bazs.map(async eventId=>{
const bazIdString = bazId.toString();
await Baz.findOne({_id:eventIdString}, {},err=>{
if(err){
reject(err);
}
});
});
resolve(result);
})
});
}
我在这两个函数中使用它:
const getBarRecursive = (taskId)=>{
return getObjectRecursive(Bar, taskId);
}
const getFooRecursive=(categoryId)=>{
return getObjectRecursive(Foo,categoryId);
};
这条路线称之为:
router.get('/:id', verifyToken, (req,res)=>{
Branch.getFooRecursive(req.params.id)
.then(
(foo)=>{
res.status(200).send(cat);
},
(err)=>{
res.status(500).send(err);
}
)
});
这意味着递归返回树对象和所有对象的子对象。发生的情况是,子对象result.children.bar
和result.children.baz
变成了永远无法兑现的承诺
我知道,这不是最好的办法。很明显,我没有做出正确的承诺。我还考虑过使用$graphLookup检索表,但我不知道如何检索,因为子项来自不同的集合
我如何让应用程序检索到任何深度的孩子
更新:这仍然不起作用。我已将递归函数更改为:
const getObjectRecursive = async (type, id)=>{
const rslt = await type.findOne.call(type, {_id:id},{}, {}, err=>{
if(err){
return({err: err});
}
});
const result = rslt.toObject();
const bars = result.bars;
const bazs = result.bazs;
result.children = {};
result.children.bars = tasks.map(async barId=>{
const barIdString = barId.toString();
await getBarRecursive(barIdString, err=>{
if(err){
reject(err);
}
});
});
result.children.bazs = bazs.map(async eventId=>{
const bazIdString = bazId.toString();
await Baz.findOne({_id:eventIdString}, {},err=>{
if(err){
reject(err);
}
});
});
return result
};
其他一切都一样。现在发生的事情是,包含条
结果的承诺直到结果发送到客户端后才得以实现,因此我在它的位置上得到了一个空对象,如下所示:
{
"bars": [
"5b626a2e325c181bdf4fba08"
],
"bazs": [],
"_id": "5b5fb27232db7b13a1090577",
"__v": 0,
"children": {
"bars": [
{}
],
"bazs": []
}
}
我尝试过的一些事情:
- 将
bar.map(async barId=>…
等)放置在Promises.all语句中,并将其分配给语句中的result.children
。然后(…)
语句
- 将
bar.map(async barId=>…
等)放在一个单独的异步函数中,然后说result.children.bar=wait getAllTasks(tasks)
如何确保在发送结果之前履行承诺?Mongoose支持承诺很长时间,不需要使用回调。拒绝
函数未定义,其使用将导致异常。此外,调用
在这里是不合理的。还有一些不一致,任务
vs 条形图
和eventId
vsbazId
。所有这些都会阻止代码正常工作
应该是这样的:
const getObjectRecursive = async (type, id)=>{
const result = await type.findOne({_id:id}).lean();
const barsPromises = result.bars.map(barId=>{
return getBarRecursive(barId.toString()); // shouldn't it accept 2 args?
});
const bazsPromises = result.bazs.map(bazId =>{
return Baz.findOne({_id:bazId.toString()}).lean();
});
const [bars, bazs] = await Promise.all([
Promise.all(barsPromises),
Promise.all(bazsPromises)
]);
result.children = { bars, bazs };
return result;
};
该示例大量使用.Mongoose支持承诺。为什么一直使用findOne回调?您将这些东西与async/await混合使用。如果您在任何地方都使用async/await,问题可能会得到解决。因此,您的意思是,与其让findObjectRecursive返回承诺,不如将其与getFooRecursive和getBarRecursive转换为async函数?如果需要,您仍然可以使用递归,但更干净的控制流会为错误留下更少的空间。const result=await type.findOne(…)
,等等。我明天会试试这个wbtw,默认情况下这样做是个好主意,除非您需要相反的方法。这样做就像const result=await type.findOne(…).lean()
。