[英]Retrieve tree data from Mongoose in recursive node function
我正在嘗試在Node Express應用中使用Mongoose從Mongodb遞歸地以樹格式檢索數據。 我正在努力兌現承諾,而我顯然做錯了。
假設您有mongodb表foos
':
{
"_id": {
"$oid": "5b5fb27232db7b13a1090577"
},
"bazs": [
{
"$oid": "5b626a2e325c181bdf4fba08"
}
],
"bars": [
{
"$oid": "5b5fb3cc32db7b13a1090579"
}
],
"name": "Parent1",
"accountId": "5b5fb27132db7b13a1090576",
"__v": 0
}
因此,它具有兩種不同類型的子對象。 同樣, baz
對象還有其他baz
對象作為子對象,還有bar
對象。 假設這是ID為bars
的表:
{
"_id": {
"$oid": "5b626a2e325c181bdf4fba08"
},
"bazs": [
{
"$oid": "5b5fb3cc32db7b75fa01"
}
],
"bars": [
{
"$oid": "5b5fb3c7cdaf740a500a"
}
],
"accountId": "5b5fb27132db7b13a1090576",
"parent": {
"$oid": "5b5fb27232db7b13a1090577"
},
"__v": 0
}
我一直在使用thunk中的遞歸函數,以等待使用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.bars
和result.children.bazs
變成了從未實現的承諾。
我知道,這不是最好的方法。 我顯然沒有正確履行諾言。 我還考慮過使用$ 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
};
其他一切都一樣。 現在發生的事情是,直到將結果發送給客戶端之后,包含bar
結果的promise才被兌現,所以我得到的是一個空對象,如下所示:
{
"bars": [
"5b626a2e325c181bdf4fba08"
],
"bazs": [],
"_id": "5b5fb27232db7b13a1090577",
"__v": 0,
"children": {
"bars": [
{}
],
"bazs": []
}
}
我嘗試過的一些事情:
bars.map(async barId=>...
等)放在Promises.all語句中,並在.then(...)
語句中將其分配給result.children
bars.map(async barId=>...
等放在單獨的異步函數中,然后說出result.children.bars = await getAllTasks(tasks)
在發送結果之前,如何確保我的諾言得到履行?
貓鼬很長一段時間都支持promise,因此無需使用回調。 reject
函數未定義,其使用將導致異常。 另外,這里的call
不合理。 還有幾個不一致的地方, tasks
vs bars
和eventId
vs bazId
。 所有這些都會阻止代碼正常工作
應該是這樣的:
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;
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.