使用分页时如何提高嵌套graphql连接的性能 [英] How to improve performance on nested graphql connections when using pagination

查看:111
本文介绍了使用分页时如何提高嵌套graphql连接的性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实施某种基本的社交网络项目.它具有 Posts Comments Like 一样.

I'm trying to implement some kind of a basic social network project. It has Posts, Comments and Likes like any other.

  • 帖子可以有很多评论
  • 帖子可以有很多赞
  • 帖子可以有一位作者

我在客户端应用程序上有一条/posts 路由.它通过分页列出 Post ,并显示其 title image authorName commentCount likesCount .

I have a /posts route on the client application. It lists the Posts by paginating and shows their title, image, authorName, commentCount and likesCount.

graphql 查询是这样的

query {
  posts(first: 10, after: "123456") {
    totalCount
    edges {
      node {
        id
        title
        imageUrl
        author {
          id
          username
        }
        comments {
          totalCount
        }
        likes {
          totalCount
        }
      }
    }
  }
}

我正在使用 apollo服务器 TypeORM PostgreSQL dataloader .我使用 dataloader 来获取每个帖子的 author .我只需将请求的 authorIds dataloader 批处理,并从 PostgreSQL 中使用 where user.id获取 authors 在authorIds 查询中,将查询结果映射到每个 authorId .您知道 dataloader 的最基本用法.

I'm using apollo-server, TypeORM, PostgreSQL and dataloader. I use dataloader to get author of each post. I simply batch the requested authorIds with dataloader, get authors from PostgreSQL with a where user.id in authorIds query, map the query result to the each authorId. You know, the most basic type of usage of dataloader.

但是,当我尝试查询每个 post 下的评论 likes 连接时,我陷入了困境.如果没有分页,我可以使用相同的技术并为它们使用 postId .但是现在我必须包括用于分页的过滤器参数.对于某些 where 条件,可能还有其他过滤器参数.

But when I try to query the comments or likes connection under each post, I got stuck. I could use the same technique and use postId for them if there was no pagination. But now I have to include filter parameters for the pagination. And there maybe other filter parameters for some where condition as well.

我找到了数据加载器的 cacheKeyFn 选项.我只是为传递给数据加载器的过滤器对象创建一个字符串键,并且它不会重复它们.它只是将唯一的传递给 batchFn .但是我无法使用 TypeORM 创建sql查询来获取每个 first after orderBy 的结果.分别进行参数传递,然后将结果映射回称为数据加载器的函数.

I've found the cacheKeyFn option of dataloader. I simply create a string key for the passed filter object to the dataloader, and it doesn't duplicate them. It just passes the unique ones to the batchFn. But I can't create a sql query with TypeORM to get the results for each first, after, orderBy arguments separately and map the results back to the function which called the dataloader.

我已经搜索了 spectrum.chat 源代码,我认为它们不允许用户查询嵌套的连接.还尝试了Github GraphQL Explorer,它可以让您查询嵌套的连接.

I've searched the spectrum.chat source code and I think they don't allow users to query nested connections. Also tried Github GraphQL Explorer and it lets you query nested connections.

有没有推荐的方法可以做到这一点?我了解了如何将 object 传递给 dataloader 并使用 cacheKeyFn 对其进行批处理,但是我不知道如何从<在一个查询中使用code> PostgreSQL 并映射结果以从加载程序中返回.

Is there any recommended way to achieve this? I understood how to pass an object to dataloader and batch them using cacheKeyFn, but I can't figure out how to get the results from PostgreSQL in one query and map the results to return from the loader.

谢谢!

推荐答案

因此,如果您稍加限制,这是可行的.限制是只允许在结果的第一页上进行批量连接,例如因此,您并行获取的所有连接都是通过参数完成的.这是一个合理的约束,因为它可以让您执行诸如获取前10个供稿项以及每个项的前3条注释之类的事情,这代表了一个非常典型的用例.试图在单个查询中支持独立分页不可能满足UI的任何实际用例,因此可能过度优化.考虑到这一点,您可以在使用PostgreSQL的PostgreSQL中支持为每个父母获得第一个N个孩子"用例.

So, if you restrict things a bit, this is doable. The restriction is to only allowed batched connections on the first page of results, e.g. so all the connections you're fetching in parallel are being done with the parameters. This is a reasonable constraint because it lets you do things like get the first 10 feed items and the first 3 comments for each of them, which represents a fairly typical use case. Trying to support independent pagination within a single query is unlikely to fulfil any real world use cases for a UI, so it's likely an over-optimisation. With this in mind, you can support the "for each parent get the first N children" use case with PostgreSQL using window.

有点儿怪异,但是有一些答案可以帮助您朝正确的方向发展:

It's a bit fiddly, but there are answers floating around which will get you in the right direction: Grouped LIMIT in PostgreSQL: show the first N rows for each group?

因此,使用dateloader与 cacheKeyFn 一起使用,并让您的加载器函数识别您是否可以执行优化(例如,在 null 之后,并且所有其他参数都相同)).如果可以优化,请使用窗口查询,否则可以像平常一样并行执行未优化的查询.

So use dateloader how you are with cacheKeyFn, and let your loader function recognise whether you can perform the optimisation (e.g. after is null and all other arguments are the same). If you can optimise, use a windowing query, otherwise do unoptimised queries in parallel as you would normally.

这篇关于使用分页时如何提高嵌套graphql连接的性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆