GraphQL:为常规列表实现窗口分页

Posted

技术标签:

【中文标题】GraphQL:为常规列表实现窗口分页【英文标题】:GraphQL : Implementing windowed pagination for regular list 【发布时间】:2016-12-20 04:41:57 【问题描述】:

我正在尝试使用“列表”实现窗口分页。我不需要基于光标的连接解决方​​案,因为我需要向用户显示编号页面。

有“User”和“Post”对象。“User”与“Post”是一对多的关系。

使用 graphql-js 作为架构, 这是我的 userType 和 postType 架构:

var userType = new GraphQLObjectType(
    name: 'User',
    fields: () => (
        id: globalIdField('User'),
        posts: 
            type: new GraphQLList(postType),
            args: 
                page:
                    type: GraphQLInt,
                    defaultValue: 0
                
            ,
            resolve: (_, args) => 
                //code to return relevant result set
            ,
        ,
        totalPosts:
            type: GraphQLInt,
            resolve: () => 
                //code to return total count
             
        ,
    ),
    interfaces: [nodeInterface],
);


var postType = new GraphQLObjectType(
    name: 'Post',
    fields: () => (
        id: globalIdField('Post'),
        name: type: GraphQLString,
        //other fields
    ),
    interfaces: [nodeInterface],
);

请注意“userType”中的“totalPosts”字段。由于将有其他列表供用户使用,并且具有相同的分页需求,因此我最终将在片段中维护大量“total Type”变量。如果我能以某种方式在 List 结果中发送 totalCount,这可以解决。

https://github.com/facebook/graphql/issues/4 这个问题讨论了在 List 上实现一个包装器以将 totalCount 包含在结果集中。

我尝试创建这样的包装器:

var postList = new GraphQLObjectType(
    name: 'PostList',
    fields:()=>(
        count: 
            type: GraphQLInt,
            resolve: ()=>getPosts().length  //this is total count
        ,
        edges: 
            type: new GraphQLList(postType),
            resolve: () => 
                return getPosts() ; // this is results for the page, though I don't know how to use 'page' argument here
            ,
        

    ),
    interfaces: [nodeInterface],
);

但是我应该如何将它连接到userTypeposts 字段?以及如何在此包装器上使用“页面”参数,就像我在原始 userType 中使用的那样?

【问题讨论】:

【参考方案1】:

我应该如何将它连接到 userType 的帖子字段?以及如何在此包装器上使用“页面”参数,就像我在原始 userType 中使用的那样?

实现您想要做的事情的一种简单方法是定义一个 dumb 包装器类型 postList,如下所示:

var postList = new GraphQLObjectType(
    name: 'PostList',
    fields:()=>(
        count:  type: GraphQLInt ,
        edges:  type: new GraphQLList(postType) 
        // Consider renaming 'edges'. In your case, it's a list, not a 
        // connection. So, it can cause confusion in the long run.
    ),
);

然后在userType 定义中,添加该包装类型的字段并定义其解析函数,如下所示。至于参数page,在定义字段类型posts时描述即可。

posts: 
    type: postList,
    args: 
        page:
            type: GraphQLInt,
            defaultValue: 0
        ,
        ...otherArgs
    ,
    resolve: async (_, page, ...otherArgs) => 
        // Get posts for the given page number.
        const posts = await db.getPosts(page);

        // Prepare a server-side object, which corresponds to GraphQL 
        // object type postList.
        const postListObj = 
            count: posts.length,
            edges: posts 
        ;
        // Consider renaming 'edges'. In your case, it's a list, not a 
        // connection. So, it can cause confusion in the long run.
    ,
,

【讨论】:

谢谢!有效。必须从 postList 包装器中删除接口:[nodeInterface] 很高兴您发现它很有用。根据您的反馈,我从 postList 包装器中删除了 interfaces 字段。谢谢!

以上是关于GraphQL:为常规列表实现窗口分页的主要内容,如果未能解决你的问题,请参考以下文章

我们如何从 GraphQL 的 RequestContextHolder 获取 GraphQL 的 HttpServletRequest(DefaultGlobalContext)(使用 graphq

无法使用 graphq-request 表示嵌套对象输入类型的数组

转换为数值失败 - GraphQL

在 GraphQL 查询中分组后如何限制和跳过标签列表页面的分页?

graphql-yoga 项目简单使用&&集成docker

GraphQL 是不是内置了分页功能?