GraphQL Dataloader 事先不知道密钥
GraphQL Dataloader not knowing keys in advance
Dataloader 可以批处理和缓存请求,但只能通过调用 load(key) 或 loadMany(keys) 来使用。
我遇到的问题是,有时我不知道我要提前加载的项目的密钥。
我正在使用 sql 数据库,当当前对象具有来自与另一个模型的 belongsTo 关系的外键时,这工作正常。
例如,属于某个组的用户具有 groupId。要解析组,您只需调用 groupLoader.load(groupId).
另一方面,如果我想解析一个组中的用户,其中可能有很多我想要一个查询,例如
SELECT * from users where user.groupId = theParticularGroupId
但是这样的查询不使用用户的密钥,所以我不确定如何使用数据加载器。
我可以做另一个请求来获取密钥,例如
SELECT id from users where user.groupId = theParticularGroupId
然后使用这些键调用 loadMany...但我本可以直接请求数据。
我注意到 dataloader 有一个 prime(key, value) 函数,它可以用来填充缓存,但是这只能在数据已经被获取后才能完成。此时许多查询已经发送,并且可能已经提取了重复数据。
另一个例子是下面的查询
query {
groups(limit: 10) {
id
...
users {
id
name
...
}
}
}
如果我搜索前 10 组或后 10 组,我无法知道密钥。然后一旦我有了这 10 个组。我不知道他们用户的密钥,如果每个解析器都会使用诸如
之类的查询来解析用户
SELECT * from users where user.groupId = theParticularGroupId
该查询将被执行 10 次。加载数据后,我现在可以填充缓存,但是已经发出了 10 个请求。
有什么办法可以解决这个问题吗?也许不同的模式或数据库结构或者数据加载器甚至都不是正确的解决方案。
您需要一个数据加载器实例来进行查找,在这种情况下,您有一个组 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
对他们进行分组来对其进行操作,该数组应根据 [=15= 的原始数组进行排序].确保你 return 没有任何用户的 groupIds 的空数组。
请注意,在此我们仅 returning 用户 ID,但您可以在拥有用户后一次性批量获取用户。您可以针对 return 用户自己稍微调整一下,您必须自己决定这是否是正确的方法。
我在 this article 中提到的一切都可以通过巧妙地使用 Dataloader 来实现。但关键要点是,您传递给 load/loadMany 函数的值不必与您尝试 return.
的对象的 ID 相对应
Dataloader 可以批处理和缓存请求,但只能通过调用 load(key) 或 loadMany(keys) 来使用。
我遇到的问题是,有时我不知道我要提前加载的项目的密钥。
我正在使用 sql 数据库,当当前对象具有来自与另一个模型的 belongsTo 关系的外键时,这工作正常。
例如,属于某个组的用户具有 groupId。要解析组,您只需调用 groupLoader.load(groupId).
另一方面,如果我想解析一个组中的用户,其中可能有很多我想要一个查询,例如
SELECT * from users where user.groupId = theParticularGroupId
但是这样的查询不使用用户的密钥,所以我不确定如何使用数据加载器。
我可以做另一个请求来获取密钥,例如
SELECT id from users where user.groupId = theParticularGroupId
然后使用这些键调用 loadMany...但我本可以直接请求数据。
我注意到 dataloader 有一个 prime(key, value) 函数,它可以用来填充缓存,但是这只能在数据已经被获取后才能完成。此时许多查询已经发送,并且可能已经提取了重复数据。
另一个例子是下面的查询
query {
groups(limit: 10) {
id
...
users {
id
name
...
}
}
}
如果我搜索前 10 组或后 10 组,我无法知道密钥。然后一旦我有了这 10 个组。我不知道他们用户的密钥,如果每个解析器都会使用诸如
之类的查询来解析用户SELECT * from users where user.groupId = theParticularGroupId
该查询将被执行 10 次。加载数据后,我现在可以填充缓存,但是已经发出了 10 个请求。
有什么办法可以解决这个问题吗?也许不同的模式或数据库结构或者数据加载器甚至都不是正确的解决方案。
您需要一个数据加载器实例来进行查找,在这种情况下,您有一个组 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
对他们进行分组来对其进行操作,该数组应根据 [=15= 的原始数组进行排序].确保你 return 没有任何用户的 groupIds 的空数组。
请注意,在此我们仅 returning 用户 ID,但您可以在拥有用户后一次性批量获取用户。您可以针对 return 用户自己稍微调整一下,您必须自己决定这是否是正确的方法。
我在 this article 中提到的一切都可以通过巧妙地使用 Dataloader 来实现。但关键要点是,您传递给 load/loadMany 函数的值不必与您尝试 return.
的对象的 ID 相对应