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

GraphQL : Implementing windowed pagination for regular list

我正在尝试使用 "List" 实现窗口分页。我不需要带有连接的基于游标的解决方案,因为我需要向用户显示编号的页面。

有 "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}" 变量。如果我能以某种方式在列表结果中发送 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 字段?我如何在这个包装器上使用 'page' 参数,就像我在原始 userType 中使用的那样?

how should I connect this to the userType's posts field? And how can I use a 'page' argument on this wrapper, like I have in original 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.
    },
},