为了执行类似于连接的操作,我们可以同时使用GraphQL和Mongoose来实现这个目的。
在提出任何问题之前,我想给出以下任务/活动示例(没有测试这些代码,只是为了示例的缘故):
Task {
_id,
title,
description,
activities: [{ //Of Activity Type
_id,
title
}]
}在猫鼬中,我们可以使用人口方法检索与任务相关的活动,如下所示:
const task = await TaskModel.findbyId(taskId).populate('activities');使用GraphQL和Dataloader,我们可以得到类似的结果:
const DataLoader = require('dataloader');
const getActivitiesByTask = (taskId) => await ActivityModel.find({task: taskId});
const dataloaders = () => ({
activitiesByTask: new DataLoader(getActivitiesByTask),
});
// ...
// SET The dataloader in the context
// ...
//------------------------------------------
// In another file
const resolvers = {
Query: {
Task: (_, { id }) => await TaskModel.findbyId(id),
},
Task: {
activities: (task, _, context) => context.dataloaders.activitiesByTask.load(task._id),
},
};我试图看看是否有文章说明哪种方法在性能、资源耗尽、...etc方面更好,但我没有找到这两种方法的任何比较。
任何洞察力都会有帮助,谢谢!
发布于 2018-10-05 16:37:13
需要注意的是,数据采集器不仅仅是数据模型的接口。虽然数据服务器被吹捧为“各种远程数据源上的简化和一致的API”--与GraphQL相结合的主要好处在于能够在单个请求的上下文中实现缓存和批处理。在处理潜在冗余数据的API中,这种功能是很重要的(考虑一下查询用户和每个用户的朋友-重新获取同一用户多次的可能性很大)。
另一方面,猫鼬的populate方法实际上只是聚合多个MongoDB请求的一种方法。从这个意义上说,比较这两者就像比较苹果和橘子。
更公平的比较可能是使用populate,如您的问题中所示,而不是按照以下方式为activities添加解析器:
activities: (task, _, context) => Activity.find().where('id').in(task.activities)无论哪种方式,问题都在于您是在父解析器中加载所有数据,还是让解析器进一步向下加载一些工作。,因为只为请求中包含的字段调用解析器,这两种方法之间可能会对性能产生重大影响。
如果请求activities字段,这两种方法将使服务器和数据库之间的往返次数相同--性能差异很小。但是,您的请求可能根本不包括activities字段。在这种情况下,永远不会调用activities解析器,我们可以通过创建一个单独的activities解析器并在那里工作来保存一个或多个数据库请求。
的相关说明.
据我所知,在MongoDB中使用$lookup之类的东西聚合查询通常比仅仅使用populate (关于这一点的一些对话可以找到这里)的性能要低。然而,在关系数据库的上下文中,在考虑上述方法时还有其他需要考虑的问题。这是因为您可以使用联接完成父解析器中的初始提取,这通常比发出单独的db请求要快得多。这意味着,以降低非活动字段查询速度为代价,您可以大大加快其他查询的速度。
https://stackoverflow.com/questions/52668154
复制相似问题