10

目前,我在graphql-java库中看不到对分页的现有支持。它确实有一些基本的中继支持,我们可以在其中创建一个connectionFacebook 推荐的实现分页的方式。
是有助于实现这一目标的方法。但是,由于没有文档,我很难理解这个函数是如何工作的。如果他们已经有一个允许使用 graphql-java 库进行基本查询的现有模型Add,那么有人可以分解他们为添加分页支持而采取的步骤吗?deletefetch

4

1 回答 1

9

您甚至不需要中继连接来支持分页。您的查询可以简单地接受页码和大小(或限制/偏移)作为参数并返回一个列表 - 完成。但是,如果您想要例如Book类型的中继连接,您可以执行以下操作:

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());

结果,您将拥有一个BookConnection符合Relay connection spec的类型。

至于基本 GraphQL 的示例,您在这里有一个简单的 Web 应用程序。

连接规范自然适合支持基于光标的分页的数据存储,但在与不同的分页样式一起使用时需要一些创造力。

1)如果您希望使用简单的基于偏移量的分页,您可以决定将after其视为偏移量(意味着将传递一个数字),并first作为限制:

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

before和相同last,只是方向不同。

2)另一种方法是将after/before视为排序列的最后看到的值(因此将传递实际(混淆)值):

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

我还建议您查看我的项目graphql-spqr,其中包含一个示例应用程序,这使得开发 GraphQL API 变得非常简单。

例如,您将创建一个这样的分页结果:

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;
    }
}

还有很多其他方法可以创建Page实例,这只是最直接的一种。

然后,您将从您的 Java 类生成一个模式:

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

并执行查询:

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

但是,同样,如果您不使用 Relay,则确实没有必要使事情过于复杂。如果您的存储自然支持基于光标的分页,那就去吧。如果没有,只需使用简单的限制/偏移参数并返回一个列表,然后忘记连接规范。它的创建是为了使 Relay 能够在各种情况下自动管理分页,因此如果您不使用 Relay 和/或基于光标的分页的数据库,它几乎总是完全矫枉过正。

于 2017-06-16T12:32:56.147 回答