【问题标题】:In Apollo GraphQL, how do I setup a resolver to not loop values?在 Apollo GraphQL 中,如何设置解析器以不循环值?
【发布时间】:2017-05-04 07:39:53
【问题描述】:

我在 Node.js 中与 Apollo-Server 和 Express.js 一起使用 Sequelize。

在进行越来越深入的查询时,GraphQL 会循环我的模型并按 ID 对每个模型进行单独的查询。

例如,如果我得到user(userId) > playthroughs > scores,这将查找该用户(没问题),然后查找与该userId 相关的所有通关(仍然没什么大不了的),然后得到分数,它循环每个playthroughId 并对每个进行完全独立的查询。这是非常低效的,并且导致我的查询花费的时间比他们应该的要长。

而不是循环:

SELECT scoreValue
FROM scores
WHERE playthroughId = id

我真的很想自己抓取数组并像这样执行循环:

SELECT scoreValue
FROM scores
WHERE playthroughId IN (...ids)

当我去年使用 Facebook 的参考 GraphQL 时也发生了这种情况,所以我认为它不是特定于 Apollo 的实现。

我想知道如何调整这些查询,以免对性能造成如此大的影响。

解析器示例:

const resolvers = {
    Query: {
        user: (_, values) => User.findOne(formatQuery(values))
            .then(getDataValues),
    },

    Playthrough: {
        score: ({ playthroughId }) => Score.findOne(formatQuery({ playthroughId }))
            .then(getDataValues),
    },

    User: {
        playthroughs: ({ userId }, { take }) => Playthrough.findAll(formatQuery({ userId, take, order: 'playthroughId DESC' }))
            .then(getAllDataValues),
    },
}

【问题讨论】:

    标签: mysql sequelize.js graphql-js apollostack apollo-server


    【解决方案1】:

    除了 graphql,facebook 还发布了一个鲜为人知的项目,dataloader

    它的作用是将同一滴答声中的多个请求批处理为一个。所以你的代码会是这样的

    scoreLoader = new Dataloader(keys => {
      return Score.findAll({ where: { id: keys } }).then(() => {
         //Map the results back so they are in the same order as keys
      })
    });
    
    
    score: ({ playthroughId }) => scoreLoader.load(playthroughId).then(getDataValues)
    

    当然,每个字段都有负载是很乏味的。因此,您可以改用 dataloader-sequelize,它将所有对 association.get 的调用(即Playthrough.getScores())和对 findOne / findById 的调用封装到数据加载器调用中,因此多个调用被分批处理。

    由于您正在构建一个由 sequelize 支持的 graphql API,您可能还对https://github.com/mickhansen/graphql-sequelize/ 感兴趣,它为 grahpql 提供了 sequelize 特定的帮助程序,并在底层使用了 dataloader-sequelize

    【讨论】:

    • 感谢您的详细解答! graphql-sequelize 不需要参考服务器而不是 Apollo 吗?此外,如果我使用 dataloader-sequelize,我将不得不设置表的关联方式是否正确?
    • 是的,它使用 facebook 实现的 grahpql 类型等 - 我不知道阿波罗制作了一个完全不同的版本。有什么好处/区别要充分利用数据加载器,您需要设置关联是的,但即使没有关联,它仍然可以将多次调用 findOne 批处理为一次调用 findAll
    猜你喜欢
    • 2017-01-11
    • 2019-07-15
    • 2021-03-25
    • 2023-03-13
    • 2020-09-11
    • 2018-10-04
    • 2021-01-25
    • 2017-04-15
    • 2021-07-29
    相关资源
    最近更新 更多