如何解决SQL 分页问题,尤其是 GraphQL 数据加载问题
我一直在研究如何建立一个新的 GraphQL API 项目,但遇到了一些基本的概念?试图找出如何有效地进行分页和嵌套数据库查询的问题。
如果您有任何指点或建议,我将不胜感激!
articles(limit: 10) {
title
content
comments(limit: 5) {
postedAt
text
}
}
一个典型的 ORM,假设急切加载嵌套类型,可以将这种类型的查询转换为这样的 sql 查询,然后循环结果以手动将评论组合在一起并将其全部合并。
select a.title,a.content,c.posted_at,c.text
from articles as a
left join comments as c on c.article_id = a.id
limit ???
但到目前为止,我只见过像 Doctrine (PHP) 和 Sequelize (js) 这样的 ORM 在这些情况下无法正确进行分页。它们无法正确处理页面大小,因为无法在此 sql 查询的设置中表达 limit
。
- => 我看到这个问题是否正确?或者我是否遗漏了一些关键的东西,ORM 是否能够以某种方式对急切加载的数据进行分页?
所以现在我刚刚在 Postgres 中遇到了 lateral
连接类型,它似乎解决了这个问题,前提是我们还添加了一些 json 技巧:
select a.title,t.data as comments
from articles as a
join lateral (
select json_agg(sub.*) as data
from (
select c.posted_at,c.text
from comments as c
where c.article_id = a.id
limit 5
) sub
) t on true
limit 20;
(我想我已经在 Hasura 和 Postgraphile 如何转换为 sql 中看到了这种 lateral
+ json 诡计,所以我不认为这是毫无根据的/糟糕的工程。)
最后,我的研究告诉我,在构建 graphql api 时,您通常会发现自己数据加载(批处理)嵌套查询,而不是从“父级”急切加载它们询问。因此,例如,这将没有数据加载:
class ArticleResolver {
comments(article) {
db.query("select ... from comments where ... = {article.id}");
}
然后这将是数据加载:
class ArticleResolver {
commentsDataLoader = new DataLoader(articleIds => {
return db.query("select ... from comments where ... in {articleIds}");
});
comments(article) {
return this.commentsDataLoader.load(article.id);
}
但是,一旦您想开始向嵌套查询添加 limit: 5
之类的参数,此数据加载查询就会变得与原始问题一样复杂,因此我们又回到了原来的位置:)
- => 是否有一些标准做法的传统方法来处理这种设置?是否有任何已知的方式/库可以如此轻松地写出解析器,例如:
class ArticleResolver
...
comments(article,limit) {
return db.somehowMagicallyDataloaded("select * from comments ... = {article.id} limit {limit}")
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。