我使用以下架构在MongoDB中保存了大约3350个文档:
const item = new Schema({
id: {
type: Number,
required: true,
index: true
},
name: {
type: String,
required: true,
index: true
},
store: {
type: Number,
required: true
},
rsbuddy: {
type: [rsbuddy],
default: []
}
})
此rsbuddy
中的item
字段通常存储了大约30,000到40,000个条目,因此我只想在请求这些文档时获取这些文档。此外,我的根GraphQL查询如下所示(它是用Apollo构建的):
const RuneScapeQuery = `
type RuneScapeQuery {
items: [Item]
item(id: Int): Item
updates: [Update]
}
`
基本上,我想要发生的是当我正在批处items
查询的请求时,我希望它默认查询所有文档。我目前有以下代码来执行此操作:
resolvers: {
RuneScapeQuery: {
items: async (root, args, { loaders }) =>
fetchItems()
.then(items => items.map(item => item.id))
.then(ids => loaders.itemLoader.loadMany(ids)),
item: (root, { id }, { loaders }) => loaders.itemLoader.load(id)
}
}
然而,这种方法的问题在于,MongoDB的第一次往返是花费所有项目的ID。其次,dataloader将为每个个人项目请求所有数据,而不是使用find
函数来检索许多文档。
const fetchItem = id =>
Item.findOne({ id }, { rsbuddy: false })
const itemLoader = new DataLoader(keys => {
return Promise.all(keys.map(fetchItem))
})
改善这种结构并简化它的好方法是什么?
修改
为了澄清我的问题,我将尝试解决主要问题的问题,那就是时间。如果您将DataLoader
添加到等式中,则会从缓存中提供项目。但是,由于始终需要首先获取实时密钥的性质,查询将保持需要11秒。第一次,它将花费大约30秒,因为它需要获取密钥然后逐个获取项目。但是,之后再次需要11秒,因为需要首先获取密钥。