Случалось ли вам когда-нибудь, чтобы при разработке API ответ оказывался очень большим json с несколькими вложенными объектами?
С одной стороны, это полезно, потому что вы получаете полный ответ в одном запросе. С другой стороны, если вам требуется только небольшая его часть, это неэффективно, потому что обычно включение вложенного объекта подразумевает более медленные запросы к базе данных, в основном из-за использования операторов JOIN.
Это также требует использования сериализаторов для построения ответа json как для основного, так и для вложенного объекта, чтобы мы могли создать полный json.
Здесь и появляется GraphQL, потому что это язык запросов, который использует схему для описания формы графа данных и позволяет запрашивать только те данные, которые вам нужны.
Не могли бы вы привести мне пример?
Если вы раньше не использовали GraphQL, я рекомендую вам прочитать эту документацию и ознакомиться с этой библиотекой.
Предположим, мы используем реляционную базу данных, в которой есть таблица компаний:
И у нас есть еще одна таблица сотрудников:
Мы хотели бы сделать два запроса: один запрашивает все поля компании, включая ее сотрудников, а другой - несколько полей без связи.
Итак, мы бы определили два типа: один для компании (GraphQLCompany
) и другой для сотрудников (GraphQLEmployee
).
Как сделать запрос к нашему API?
Мы могли бы создать запрос GraphQL, который выбирает компанию со всеми ее атрибутами, как показано ниже:
У нас может быть другой запрос, который выбирает только компанию с некоторыми ее атрибутами. В этом случае, если не получить сотрудников, дополнительный запрос не выполняется.
Мы можем сделать HTTP-запрос POST к нашему API, используя этот запрос в качестве тела, или использовать клиентскую библиотеку, такую как Apollo client, что упрощает задачу.
Давайте реализуем запрос GraphQL
Мы определяем запрос getCompanyById
, который действует как контроллер в нашем API. Этот запрос GraphQL имеет функцию разрешения, которая получает идентификатор в качестве аргумента и возвращает тип GraphQLCompany
.
Мы видим, что у нас есть объект репозитория для доступа к базе данных, получения информации о компании и возврата модели компании в функции разрешения запроса. Мы не сериализуем ответ, потому что GraphQLCompany
type отвечает за сериализацию, обращаясь к полям возвращаемого объекта.
Как определить тип GraphQL?
Когда мы определяем запрос в нашем API, мы указываем тип ответа, поэтому объект, который возвращает запрос, должен соответствовать определению типа. Каждое поле в определении типа соответствует возвращаемому объекту.
Так что в случае сотрудников требуется дополнительный запрос. В этом случае мы используем преобразователи настраиваемых полей. Это функции, которые выполняются, если поле запрашивается в запросе, что позволяет нам выполнять дополнительный запрос к базе данных только тогда, когда это необходимо.
Давайте определим тип GraphQL компании, в котором мы укажем его атрибуты:
Мы видим, что у нас есть модель компании, которую мы определяем с помощью нашего объектно-реляционного сопоставления (ORM), и каждое поле является столбцом в модели, но где же сотрудники? Мы знаем, что для того, чтобы получить ассоциацию, мы должны выполнить дополнительные запросы к базе данных, но только тогда, когда поле запрошено, так что именно здесь решатели полей вступают в игру.
Давайте сначала определим тип GraphQL сотрудника:
Затем мы можем добавить поле «Сотрудники» к типу «Компания».
Наконец, мы видим, что модель Company из нашего ORM связана с моделью Employee, где мы можем выполнить дополнительный запрос с помощью простого company.getEmployees()
method, и операция выполняется только в том случае, если поле запрошено, потому что функция разрешения будет выполняться только в том случае, если поле является частью запроса, который получает наш API.
Заключение
Это лишь некоторые из рекомендаций, которые я узнал из своего опыта использования GraphQL. Сначала я допустил классическую ошибку, создав свой собственный сериализатор для использования в ответах на каждый запрос или мутацию, пока я не понял цель строгой типизации, которую дает нам GraphQL.
Теперь ваша очередь отправиться в путешествие по GraphQL!