die*_*uge 7 javascript sql graphql apollo-server
我想知道在使用 Dataloader 时如何最好地处理 GraphQL 字段参数是否有任何共识。batchFnDataloader 需要的批处理函数期望接收Array<key>并返回一个Array<Promise>,通常只调用load( parent.id )whereparent是给定字段的解析器的第一个参数。在大多数情况下,这很好,但是如果您需要为嵌套字段提供参数怎么办?
例如,假设我有一个 SQL 数据库,其中包含用于Users, 的表Books,以及一个称为BooksRead表示用户:书籍之间 1:many 关系的关系表。
我可能会运行以下查询来查看所有用户阅读的书籍:
query {
users {
id
first_name
books_read {
title
author {
name
}
year_published
}
}
}
Run Code Online (Sandbox Code Playgroud)
假设在 中有一个BooksReadLoaderavailable context,这样解析器 forbooks_read可能如下所示:
const UserResolvers = {
books_read: async function getBooksRead( user, args, context ) {
return await context.loaders.booksRead.load( user.id );
}
};
Run Code Online (Sandbox Code Playgroud)
的批处理加载函数BooksReadLoader将async调用数据访问层方法,该方法将运行一些 SQL,如:
SELECT B.* FROM Books B INNER JOIN BooksRead BR ON B.id = BR.book_id WHERE BR.user_id IN(?);
Run Code Online (Sandbox Code Playgroud)
我们将从Book结果行创建一些实例, group by user_id,然后返回keys.map(fn)以确保我们将正确的书分配给user_id加载器缓存中的每个键。
现在假设我向 中添加一个参数books_read,询问用户阅读的所有 1950 年之前出版的书籍:
query {
users {
id
first_name
books_read(published_before: 1950) {
title
author {
name
}
year_published
}
}
}
Run Code Online (Sandbox Code Playgroud)
理论上,我们可以运行相同的 SQL 语句,并在解析器中处理参数:
const UserResolvers = {
books_read: async function getBooksRead( user, args, context ) {
const books_read = await context.loaders.booksRead.load( user.id );
return books_read.filter( function ( book ) {
return book.year_published < args.published_before;
});
}
};
Run Code Online (Sandbox Code Playgroud)
但是,这并不理想,因为我们仍在从Books表中获取潜在的大量行,而实际上可能只有少数行满足该参数。改为执行此 SQL 语句要好得多:
SELECT B.* FROM Books B INNER JOIN BooksRead BR ON B.id = BR.book_id WHERE BR.user_id IN(?) AND B.year_published < ?;
Run Code Online (Sandbox Code Playgroud)
我的问题是,cacheKeyFn可用的选项 via 是否new DataLoader( batchFn[, options] )允许向下传递字段的参数以在数据访问层中构造动态 SQL 语句?我已经查看了https://github.com/graphql/dataloader/issues/75但我仍然不清楚是否cacheKeyFn是要走的路。我正在使用apollo-server-express. 还有另一个 SO 问题:使用 Facebook 的 DataLoader 传递参数,但它没有答案,我很难找到其他来源。
谢谢!
将 id 和 params 作为单个对象传递给加载函数,如下所示:
const UserResolvers = {
books_read: async function getBooksRead( user, args, context ) {
return context.loaders.booksRead.load({id: user.id, ...args});
}
};
Run Code Online (Sandbox Code Playgroud)
然后让批量加载函数弄清楚如何以最佳方式满足它。
您还需要对对象的构造进行一些记忆,因为否则数据加载器的缓存将无法正常工作(我认为它是基于身份而不是深度相等来工作的)。
| 归档时间: |
|
| 查看次数: |
1595 次 |
| 最近记录: |