使用分页时如何提高嵌套graphql连接的性能 [英] How to improve performance on nested graphql connections when using pagination
问题描述
我正在尝试实施某种基本的社交网络项目.它具有 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屋!