【问题标题】:How to use dataloader?如何使用数据加载器?
【发布时间】:2020-07-30 01:18:25
【问题描述】:

我正在努力解决这个问题。

我想从我的数据库中获取我所有的用户,缓存他们 然后在发出新请求时,我想获取我缓存的那些+已创建的新请求。

到目前为止:

const batchUsers = async ({ user }) => {
  const users = await user.findAll({});

  return users;
};

const apolloServer = new ApolloServer({
  schema,
  playground: true,
  context: {
    userLoader: new DataLoader(() => batchUsers(db)),// not sending keys since Im after all users
  },
});

我的解析器:

    users: async (obj, args, context, info) => {
      return context.userLoader.load();
}

load 方法需要一个参数,但在这种情况下,我不想拥有一个特定的用户,我想要所有这些。

我不明白如何实现这一点,请有人解释一下。

【问题讨论】:

    标签: javascript graphql sequelize.js dataloader


    【解决方案1】:

    如果您只是尝试加载所有记录,那么开始使用 DataLoader 并没有多大意义。DataLoader 背后的目的是将多个调用(如 load(7)load(22))批处理到一个调用中,即然后针对您的数据源执行。如果您需要获取所有用户,那么您应该直接拨打user.findAll

    另外,如果您最终使用 DataLoader,请确保您传入的是函数,而不是对象作为上下文。该函数将在每个请求上运行,这将确保您使用的是新的 DataLoader 实例,而不是具有陈旧缓存的实例。

    context: () => ({
      userLoader: new DataLoader(async (ids) => {
        const users = await User.findAll({
          where: { id: ids }
        })
    
        // Note that we need to map over the original ids instead of
        // just returning the results of User.findAll because the
        // length of the returned array needs to match the length of the ids
        return ids.map(id => users.find(user => user.id === id) || null)
      }),
    }),
    

    请注意,如果您希望 load 拒绝,您也可以在数组内返回错误实例而不是 null

    【讨论】:

    • 感谢您的解释。 Jump启动了我的大脑。我确实意识到我选择了一个糟糕的例子来获取所有用户。为清楚起见,您是否介意添加一个示例,其中像上面解释的那样进行批处理会很有用。再次感谢!
    • 编辑答案以包含完整示例
    • 谢谢!在额外的编辑中,我可能有点不清楚。希望看到您实际使用数据加载器的场景。我与感染用户的例子相当糟糕,我想也许你可以分享一个你使用它的场景。接受答案,如果额外的要求不是太多,我会很高兴!
    【解决方案2】:

    花了我一段时间,但我得到了这个工作:

    const batchUsers = async (keys, { user }) => {
      const users = await user.findAll({
        raw: true,
        where: {
          Id: {
            // @ts-ignore
            // eslint-disable-next-line no-undef
            [op.in]: keys,
          },
        },
      });
    
      const gs = _.groupBy(users, 'Id');
      return keys.map(k => gs[k] || []);
    };
    
    const apolloServer = new ApolloServer({
      schema,
      playground: true,
      context: () => ({
        userLoader: new DataLoader(keys => batchUsers(keys, db)),
      }),
    });
    

    解析器:

      user: {
        myUsers: ({ Id }, args, { userLoader }) => {
          return userLoader.load(Id);
        },
      },
    

    游乐场:

    {users
    {Id
    myUsers
    {Id}}
    }
    

    游乐场解释:

    users 基本上会获取所有用户,然后 myusers 通过从第一次调用中继承 id 来做同样的事情。

    我想我在这里选择了一个可怕的例子,因为我没有看到任何性能提升。然而,我确实看到查询变成了:

    SELECT ... FROM User WhERE ID IN(...)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-16
      • 1970-01-01
      • 2019-12-23
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多