如何使用数据加载器?

How to use dataloader?

我正在想办法解决这个问题。

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

到目前为止:

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 方法需要一个参数,但在这种情况下,我不想拥有一个特定的用户,我想要所有的用户。

我不明白如何实现这个,谁能解释一下。

如果您只想加载所有记录,那么开始使用 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 拒绝,您也可以 return 一个错误实例而不是数组中的 null

花了我一段时间,但我开始工作了:

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(...)