GraphQL: как реализовать разбиение на страницы с GraphQL-Java?
В настоящее время я не вижу поддержки пагинации в библиотеке graphql-java. Он имеет некоторую базовую поддержку ретрансляции, где мы можем создать connection
Facebook рекомендовал способ реализации нумерации страниц.
Это метод, который помогает достичь этого. Однако без документации мне трудно понять, как работает эта функция. Может ли кто-то разбить шаги, которые они предпримут, чтобы добавить поддержку нумерации страниц, если у них уже есть существующая модель, которая допускает базовые запросы, такие как Add
, delete
, fetch
и т.д., используя библиотеку graphql-java?
1 ответ
Вам даже не нужны релейные соединения для поддержки нумерации страниц. Ваш запрос может просто принять номер страницы и размер (или ограничение / смещение) в качестве аргументов и вернуть список - готово. Но, если вы хотите, чтобы релейное соединение, например, 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
тип, соответствующий спецификации соединения реле.
Что касается примера с базовым GraphQL, у вас есть простое веб-приложение здесь.
Спецификация соединения естественно подходит для хранилища данных, которое поддерживает нумерацию на основе курсора, но требует некоторой креативности при использовании с разными стилями нумерации страниц.
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 с примером приложения, которое упрощает разработку API-интерфейсов GraphQL.
Например, вы бы создали результат с разбивкой по страницам, например так:
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, вам не нужно слишком усложнять вещи. Если ваше хранилище поддерживает пагинацию на основе курсора, сделайте это. Если это не так, просто используйте простые аргументы limit /offset и верните список, и забудьте о спецификации соединения. Он был создан для того, чтобы Relay автоматически управлял подкачкой в различных сценариях, поэтому почти всегда это полный перебор, если вы не используете Relay и / или DB с пагинацией на основе курсора.