微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SQL 分页问题,​​尤其是 GraphQL 数据加载问题

如何解决SQL 分页问题,​​尤其是 GraphQL 数据加载问题

我一直在研究如何建立一个新的 GraphQL API 项目,但遇到了一些基本的概念?试图找出如何有效地进行分页和嵌套数据库查询的问题。

如果您有任何指点或建议,我将不胜感激!

假设我们得到一个像这样的 graphql 查询

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 诡计,所以我不认为这是毫无根据的/糟糕的工程。)

  • => 是否有任何 ORM(除了 hasura/postgraphile),可能是 Postgres 特定的,使用这种 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 举报,一经查实,本站将立刻删除。