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

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

问题描述

我正在尝试实施某种基本的社交网络项目.它有 PostsComments Likes 和其他任何东西一样.

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

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

我在客户端应用程序上有一个 /posts 路由.它通过分页列出 Posts 并显示它们的 titleimageauthorNamecommentCount> 和 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-serverTypeORMPostgreSQLdataloader.我使用 dataloader 来获取每个帖子的 author.我只是用 dataloader 批处理请求的 authorIds,从 PostgreSQL 获取 authorswhere user.id在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 下的 commentslikes 连接时,我被卡住了.如果没有分页,我可以使用相同的技术并为它们使用 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.

我找到了 dataloader 的 cacheKeyFn 选项.我只是为传递给数据加载器的过滤器对象创建一个字符串键,它不会复制它们.它只是将唯一的传递给 batchFn.但是我无法使用 TypeORM 创建 sql 查询来获取每个 firstafterorderBy 的结果单独的参数并将结果映射回调用数据加载器的函数.

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 对它们进行批处理,但我不知道如何从 object 获取结果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 使用窗口支持为每个父级获取前 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.

这有点繁琐,但有一些答案可以帮助您找到正确的方向:PostgreSQL 中的分组限制:显示每组的前 N ​​行?

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,并让您的加载器函数识别您是否可以执行优化(例如 after is 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天全站免登陆