簡體   English   中英

在遞歸節點函數中從Mongoose檢索樹數據

[英]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.barsresult.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 barseventId 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM