javascript - javascript中的嵌套MongoDB查询
问题描述
这是一个 GraphQL 解析器。问题在于使用异步/等待的承诺处理。
我尝试过实现 promise 处理,但我无法正确设置它,我在 promise 处理方面没有太多经验,一些学习资料会很有帮助。
我的理解是脚本将在调用 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
}
})
}),
预期的返回值应该有“publication_year”作为某个年份,它现在给出 null。
感谢帮助
解决方案
您似乎将 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
管道在单个调用中而不是在 map 循环中调用其他集合来获取。考虑以下管道
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
}
}
推荐阅读
- c# - 如何将数据从 ASP.NET 传递到 ASP.Net Core 应用程序?
- angular - Angular Hybrid 应用程序单元测试
- java - jooq 为 Oracle 返回没有时间的日期
- android - onClick 崩溃(通过在与 setText() 一起使用之前将 int 转换为 String 来解决问题)
- c# - 如何对文本框中的用户输入值进行排序并打印在标签中?
- python - 使用 factory_boy 数据填充特定数据库以进行测试
- android - 如何在 Android Google Map API 中管理不在集群中的点击标记?
- ffmpeg - 使用包含专辑封面的 ffmpeg 裁剪 mp3 文件
- jquery - 在所有页面上切换滚动类,除了一个
- ftp - 如何通过 FTP 发送我最近的数据集?