GraphQL:如何用graphQL-java实现分页?
GraphQL: How to implement pagination with graphQL-java?
目前,我发现 graphql-java 库中不支持分页。它确实有一些基本的中继支持,在其中,我们可以创建一个 connection
,Facebook 推荐的实现分页的方式。
This 是帮助实现这一目标的方法。但是,由于没有文档,我发现很难理解此功能的工作原理。如果有人已经有了一个允许基本查询如 Add
、delete
、fetch
等的现有模型,那么有人可以分解他们添加分页支持的步骤吗?使用 graphql-java 图书馆?
您甚至不需要中继连接来支持分页。您的查询可以简单地接受页码和大小(或 limit/offset)作为参数和 return 列表 - 完成。
但是,如果您想要中继连接,例如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());
因此,您将拥有一个符合 Relay connection spec.
的 BookConnection
类型
至于使用基本 GraphQL 的示例,您有一个简单的 Web 应用程序 here。
连接规范自然适合支持基于游标的分页的数据存储,但在与不同的分页样式一起使用时需要一些创意。
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, with an example app,它使开发 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 class:
生成一个架构
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,那么真的没有必要让事情变得过于复杂。如果您的存储自然地支持基于游标的分页,那就去吧。如果没有,只需使用简单的 limit/offset 参数和 return 列表,并忘记连接规范。它的创建是为了使 Relay 能够在各种情况下自动管理分页,因此如果您不使用 Relay and/or 具有基于游标的分页的数据库,它几乎总是完全矫枉过正。
目前,我发现 graphql-java 库中不支持分页。它确实有一些基本的中继支持,在其中,我们可以创建一个 connection
,Facebook 推荐的实现分页的方式。
This 是帮助实现这一目标的方法。但是,由于没有文档,我发现很难理解此功能的工作原理。如果有人已经有了一个允许基本查询如 Add
、delete
、fetch
等的现有模型,那么有人可以分解他们添加分页支持的步骤吗?使用 graphql-java 图书馆?
您甚至不需要中继连接来支持分页。您的查询可以简单地接受页码和大小(或 limit/offset)作为参数和 return 列表 - 完成。
但是,如果您想要中继连接,例如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());
因此,您将拥有一个符合 Relay connection spec.
的BookConnection
类型
至于使用基本 GraphQL 的示例,您有一个简单的 Web 应用程序 here。
连接规范自然适合支持基于游标的分页的数据存储,但在与不同的分页样式一起使用时需要一些创意。
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, with an example app,它使开发 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 class:
生成一个架构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,那么真的没有必要让事情变得过于复杂。如果您的存储自然地支持基于游标的分页,那就去吧。如果没有,只需使用简单的 limit/offset 参数和 return 列表,并忘记连接规范。它的创建是为了使 Relay 能够在各种情况下自动管理分页,因此如果您不使用 Relay and/or 具有基于游标的分页的数据库,它几乎总是完全矫枉过正。