Вложенный запрос MongoDB в JavaScript - PullRequest
2 голосов
/ 01 июля 2019

Это распознаватель GraphQL. Проблема в обработке обещаний с использованием async / await.

Я пытался реализовать обработку обещаний, но я не могу правильно ее настроить, у меня нет большого опыта в обработке обещаний, некоторые учебные материалы окажут большую помощь.

Насколько я понимаю, сценарий остановится при вызове 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
            }
        })
    }),

Ожидаемое возвращаемое значение должно иметь значение "публикации_год", равное некоторому году, теперь оно равно нулю.

Спасибо за помощь

1 Ответ

0 голосов
/ 01 июля 2019

Вы, кажется, смешиваете Promises с async / await , и за ним немного трудно следовать.Всегда лучше разбить ваш код, изменив биты Promise на async / await , так как это поможет вам сузить проблему.Вы также можете заключить весь блок в try / catch , что позволяет относительно легко обрабатывать как синхронные, так и асинхронные ошибки.

Итак, для начала вы можете изменить вызов функции контекстакоторый возвращает обещание использовать async await как

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
    }
}

Вызов другой коллекции для получения publication_year может быть выполнен с использованием конвейера $lookup в одном вызове, а не в цикле карты.Рассмотрим следующий конвейер

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
    }
}
...