简体   繁体   English

GraphQL:如何用graphQL-java实现分页?

[英]GraphQL: How to implement pagination with graphQL-java?

Currently, I see no existing support for pagination in the graphql-java library. 目前,我看不到graphql-java库中对分页的支持。 It does have some basic relay support, where-in, we can create a connection , Facebook's recommended way of implementing pagination. 它确实有一些基本的中继支持,在哪里,我们可以创建一个connection ,Facebook的推荐方式实现分页。
This is the method which helps achieve that. 是帮助实现这一目标的方法。 However, with no documentation I'm finding it hard to understand how this function works. 但是,由于没有文档,我发现很难理解这个函数是如何工作的。 Can someone break-down the steps they would take to add pagination support if they already have an existing model which allows basic queries like Add , delete , fetch etc. using the graphql-java library? 如果他们已经有一个允许使用graphql-java库进行基本查询(如Adddeletefetch等)的现有模型,是否有人可以分解他们为添加分页支持而采取的步骤?

You don't even need Relay connections to support pagination. 您甚至不需要中继连接来支持分页。 Your query could simply accept a page number and size (or limit/offset) as arguments and return a list - done. 您的查询可以简单地接受页码和大小(或限制/偏移)作为参数并返回列表 - 完成。 But, if you wanted Relay connection for eg Book type, you'd do something like the following: 但是,如果您想要例如Book类型的Relay连接,您可以执行以下操作:

Relay relay = new Relay();
GraphQLOutputType book = ...; //build your normal Book object type
GraphQLObjectType bookEdge = relay.edgeType(book.getName(), book, null, Collections.emptyList());
GraphQLObjectType bookConnection = relay.connectionType(book.getName(), bookEdge, Collections.emptyList());

As a result, you'd have a BookConnection type that conforms to the Relay connection spec . 因此,您将拥有符合中继连接规范BookConnection类型。

As for the example with basic GraphQL, you have a simple web app here . 至于基本GraphQL的示例,您可以在此处使用简单的Web应用程序。

The connection spec naturally fits a data store that supports cursor based pagination, but needs some creativity when used with different pagination styles. 连接规范自然适合支持基于光标的分页的数据存储,但在与不同的分页样式一起使用时需要一些创造力。

1) If you wish to use simple offset based paging, you can decide to treat after as the offset (meaning a number would be passed), and first as the limit: 1)如果您希望使用简单的偏移分页基础,你可以决定治疗after的偏移量(意思是数量将通过),并first为限:

SELECT * FROM ORDER BY timestamp OFFSET $after LIMIT $first

The same for before and last , just different direction. 同为beforelast ,只是不同的方向。

2) Another way is to treat after / before as the last seen value of the sort column (so an actual (obfuscated) value would be passed): 2)另一种方法是将after / before视为sort列的最后一次看到的值(因此将传递一个实际的(模糊的)值):

SELECT * FROM ORDER BY timestamp WHERE timestamp > $after LIMIT $first

I'd also recommend you take a look at my project, graphql-spqr , with an example app , that makes developing GraphQL APIs dead simple. 我还建议您使用示例应用程序查看我的项目graphql-spqr ,这使得开发GraphQL API变得简单。

For example, you'd create a paginated result like this: 例如,您将创建一个分页结果,如下所示:

public class BookService {
    @GraphQLQuery(name = "books")
    //make sure the argument names and types match the Relay spec
    public Page<Book> getBooks(@GraphQLArgument(name = "first") int first, @GraphQLArgument(name = "after") String after) {
        //if you decide to fetch from a SQL DB, you need the limit and offset instead of a cursor
        //so, you can treat "first" as count as "after" as offset
        int offset = Integer.valueOf(after);
        List<Book> books = getBooksFromDB(first, offset);
        Page<Book> bookPage = PageFactory.createOffsetBasedPage(books, totalBookCount, offset);
        return bookPage;
    }
}

There's many other ways to create a Page instance, this is just the most straight-forward one. 还有很多其他方法可以创建一个Page实例,这只是最简单的方法。

You'd then generate a schema from your Java class: 然后,您将从Java类生成一个模式:

GraphQLSchema schema = new GraphQLSchemaGenerator()
       .withOperationsFromSingleton(new BookService())
       .generate();
GraphQL graphQL = GraphQLRuntime.newGraphQL(schema).build();

And execute a query: 并执行查询:

ExecutionResult result = graphQL.execute("{books(first:10, after:\"20\") {" +
                "   pageInfo {" +
                "       hasNextPage" +
                "   }," +
                "   edges {" +
                "       cursor, node {" +
                "           title" +
                "}}}}");

But, again, if you are not using Relay there's really no need to overcomplicate things . 但是, 如果你不使用Relay,那么真的没有必要使事情过于复杂 If your storage supports cursor-based pagination naturally, go for it. 如果您的存储自然支持基于游标的分页,请选择它。 If it doesn't, just use the simple limit/offset arguments and return a list, and forget the connection spec. 如果没有,只需使用简单的limit / offset参数并返回一个列表,并忘记连接规范。 It was created to enable Relay to automatically manage paging in various scenarios, so it's almost always a total overkill if you're not using Relay and/or a DB with cursor-based pagination. 它的创建是为了使Relay能够在各种场景下自动管理分页,因此如果你没有使用Relay和/或带有基于光标的分页的DB,那么它几乎总是有点过分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM