GraphQL Dataloader事先不知道密钥

时间:2018-02-18 12:41:46

标签: javascript node.js caching graphql batching

Dataloader能够批量处理和缓存请求,但只能通过调用load(key)或loadMany(keys)来使用它。

我遇到的问题是有时候我不知道他们要提前加载的物品的钥匙。

我正在使用sql数据库,当当前对象具有与另一个模型的belongsTo关系的外键时,这可以正常工作。

例如,属于某个组的用户具有groupId。要解析该组,您只需调用groupLoader.load(groupId)。

另一方面,如果我想解决一个群组中的用户,其中可能会有很多我想要查询的用户,例如

SELECT * from users where user.groupId = theParticularGroupId

但是像这样的查询不使用用户的密钥,因此我不确定如何使用dataloader。

我可以再做一个获取

等密钥的请求
SELECT id from users where user.groupId = theParticularGroupId

然后使用这些键调用loadMany ......但我可以直接请求数据。

我注意到dataloader有一个prime(key,value)函数,可以用来填充缓存,但是只有在数据被提取后才能执行。此时已经发送了许多查询,并且可以获取重复数据。

另一个例子是以下查询

query {
  groups(limit: 10) {
    id
    ...
    users {
      id
      name
      ...
    }
  }
}

如果我正在搜索第一组或最后10组,我无法知道密钥。一旦我有了这10组。我无法知道其用户的密钥,以及每个解析器是否会使用诸如

之类的查询来解析用户
SELECT * from users where user.groupId = theParticularGroupId

该查询将被执行10次。加载数据后,我现在可以填充缓存,但已经完成了10个请求。

有没有解决这个问题的方法?也许不同的模式或数据库结构或者数据加载器甚至都不是正确的解决方案。

1 个答案:

答案 0 :(得分:3)

您需要一个可以进行查找的数据加载器实例,在这种情况下,您有一个组ID并且您想要用户:

import DataLoader from 'dataloader';

const userIdsForGroupLoader = new DataLoader(groupIds => batchGetUsersIdsForGroups(groupIds));

现在,您的batchGetUsersForGroups函数基本上必须将组ID数组转换为用户数组数组(每个组的一个用户ID数组)。

您将从IN查询开始:

SELECT id from users where user.groupId in (...groupIds)

这将为您提供单个用户结果集,您必须通过它们groupId对其进行分组来操作,数组应根据groupIds的原始数组进行排序。确保为没有任何用户的groupId返回一个空数组。

请注意,在此我们只返回用户ID,但是一旦拥有用户ID,您就可以一次性批量获取用户。您可以稍微调整一下以返回用户自己,如果这是正确的方法,您必须自己决定。

我在this article中提到的一切都可以通过巧妙地使用Dataloader来实现。但关键的一点是,传递给load / loadMany函数的值不必与您尝试返回的对象的ID相对应。