【问题标题】:Nested MongoDB query in javascriptjavascript中的嵌套MongoDB查询
【发布时间】:2019-11-11 16:36:36
【问题描述】:

这是一个 GraphQL 解析器。 问题在于使用 async/await 处理承诺。

我尝试过实现promise处理,但我无法正确设置它,我对promise处理没有太多经验,一些学习资料会很有帮助。

我的理解是脚本将在调用 await 的地方停止,并在 await 调用完成后继续。但它绕过了等待。 返回值后等待调用结束

    allDocs: async (args, context) => context().then(async client => {
        let db = client.db(dbName)
        const id = args.identifier.trim()
        let nameArr = []
        return await db.collection("collection").find({
            $or: [{
                "a.iden": id
            }, {
                "b.iden": id
            }]
        }).toArray().then(async (arr) => {
            let year
            arr.map(async element => {
                let pmcid = element.pmc_id.toUpperCase()      
                try {
                    year = await db.collection("Another_collection").findOne({"pmcid" : query})["year"]
                } catch (e) {
                    year = null
                }
                element["publication_year"] = year
            })
            return await arr
        }).then((arr)=>{
            client.close()
            return {
                "documents":  arr,
                "count": arr.length,
                "searchkey": id
            }
        })
    }),

预期的返回值应该有“publication_year”作为某个年份,它现在给出null。

感谢您的帮助

【问题讨论】:

    标签: javascript node.js mongodb aggregation-framework graphql


    【解决方案1】:

    您似乎将 Promises 与 async/await 混合在一起,这有点难以理解。通过更改 Promise 位以使用 async/await 来分解代码总是更好,因为这将帮助您缩小问题范围。您也可以将整个块包装在 try/catch 中,这样可以相对轻松地处理同步和异步错误。

    因此,首先,您可以更改上下文函数调用,该函数调用返回一个使用 async await as 的承诺

    allDocs: async (args, context) => {
        try {
            const client = await context()
    
            ....
        } catch(err) {
    
        }
    }
    

    然后对 toArray() 函数调用执行相同的操作,该函数调用返回一个可以通过 async/await 解决的承诺:

    allDocs: async (args, context) => {
        try {
            const client = await context()
            const db = client.db(dbName)
            const id = args.identifier.trim()
            const results = await db.collection('collection').find({
                '$or': [
                    { 'a.iden': id }, 
                    { 'b.iden': id }
                ]
            }).toArray()
    
            const arr = results.map(async doc => {
                const pmcid = doc.pmc_id.toUpperCase()
                const { year } = await db.collection('Another_collection')
                                         .findOne({'pmcid' : pmcid })
    
                return {
                    ...doc,
                    publication_year: year
                }
            })
    
            client.close()
    
            return {
                'documents':  arr,
                'count': arr.length,
                'searchkey': id
            }
        } catch(err) {
            // handle error
        }
    }
    

    可以使用$lookup 管道在单个调用中而不是在映射循环中调用另一个集合以获取publication_year。考虑以下管道

    allDocs: async (args, context) => {
        try {
            const client = await context()
            const db = client.db(dbName)
            const id = args.identifier.trim()
            const pipeline = [
                { '$match': {
                    '$or': [
                        { 'a.iden': id }, 
                        { 'b.iden': id }
                    ]
                } },
                { '$lookup': {
                    'from': 'Another_collection',
                    'let': { 'pmcId': '$pmc_id' },
                    'pipeline': [
                        { '$match': { 
                            '$expr': { 
                                '$eq': [
                                    '$pmcid', 
                                    { '$toUpper': '$$pmcId' }
                                ] 
                            }
                        } }
                    ],
                    'as': 'pmc'
                } },
                { '$addFields': {
                    'publication_year': { 
                        '$arrayElemAt': [ '$pmc.year', 0 ]
                    }
                } },
                { '$project': { 'pmc': 0 } }
            ]
            const arr = await db.collection('collection').aggregate(pipeline).toArray()
    
            client.close()
    
            return {
                'documents':  arr,
                'count': arr.length,
                'searchkey': id
            }
        } catch(err) {
            // handle error
        }
    }
    

    【讨论】:

    • 谢谢,很高兴知道聚合方法,它让事情变得简单并开辟了新的维度。
    猜你喜欢
    • 2015-11-19
    • 2021-06-20
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    • 2015-05-20
    • 1970-01-01
    • 2020-01-21
    • 2023-03-08
    相关资源
    最近更新 更多