Pull to refresh

Анатомия запросов GraphQL

Reading time 5 min
Views 36K
Original author: Sashko Stubailo

Джентльменский набор терминов


Новый стандарт получения данных GraphQL стал популярен совсем недавно. Сейчас активно обсуждается развитие этой технологии, появляются все новые инструменты. Одно из достоинств GraphQL – он дает команде разработчиков универсальный язык для описания того, какие данные доступны в API. Но в каких терминах обсуждать сам язык запросов и технологию в целом?


Спецификация GraphQL содержит почти исчерпывающий набор терминов по всем аспектам GraphQL. Но спецификация довольно объемна. В этой статье мы на конкретных примерах узнаем наиболее важные понятия и термины, которых достаточно для обсуждения GraphQL на уровне специалиста.


Примечание – Эта статья не лучший выбор для изучения GraphQL с нуля. Сначала рекомендуется ознакомиться с материалами на сайте graphql.org, попробовать GraphQL в превосходном курсе Изучаем Apollo и затем вернуться к статье, чтобы погрузиться в язык технических терминов.


Основные запросы GraphQL


Часто запросом называют все, что уходит на сервер GraphQL. С этим связана некоторая путаница. Что является задачей для сервера, о выполнении которой его просят? Это может быть запрос данных (query), мутация (mutation) или подписка (subscription). Слово «запрос» прочно ассоциируется с сетевым запросом в понимании HTTP и транспортного уровня. Поэтому начать следует с нескольких общих понятий:


  • Документ GraphQL (GraphQL document). Строка на языке GraphQl, описывающая одну или несколько операций или фрагментов.
  • Операция (Operation). Единичный запрос данных, мутация или подписка, которые интерпретирует исполняемый модуль GraphQL.

Из чего состоит простейшая операция? Для примера возьмем очень простой документ GraphQL.


image
Рис. Составные части простого запроса.


Здесь показаны основные конструкции GraphQL, с помощью которых описываются запрашиваемые данные.


  • Поле (Field). Единица запрашиваемых данных, которая становится полем в ответе JSON. Обратите внимание, эти части называются «полями», как бы глубоко не находились в структуре запросе. Поле на вершине операции действует так же, как находящееся уровнем глубже.
  • Аргументы (Arguments). Набор пар ключ-значение, связанных с конкретным полем. Они передаются на сервер обработчику поля и влияют на получение данных. Аргументы могут быть литералами, как показано выше, или переменными, как в следующем примере. Надо отметить, что аргументы могут быть у любого поля, независимо от его уровня вложенности.

Приведенный выше запрос является несколько сокращенной формой GraphQL, позволяющей выразить потребность в данных максимально лаконично. Но операция GraphQL может включать еще три дополнительные части. Они используются, когда необходимо выполнить иное действие, чем запрос данных, или отправить динамически сформированные переменные.


В следующем примере показаны все эти части.


image
Рис. Более детальный запрос и его составные части.


  • Тип операции (Operation type). Возможно одно из трех значений: query, mutation, subscription, что указывает на тип выполняемой операции. Хотя языковые конструкции с разными операциями выглядят похоже, спецификация GraphQL предусматривает для них отличающиеся режимы выполнения на сервере.
  • Имя операции (Operation name). Присваивать имена удобно для отладки и логирования на сервере. Если что-не так в сетевых логах или инструмент типа Apollo Optics показывает проблемы на сервере GraphQL, легче найти проблемный запрос в проекте по имени, чем разбирать содержимое запроса. Имя операции подобно имени функции в языке программирования.
  • Определение переменных (Variable definitions). Запрос GraphQL может иметь динамическую часть, которая меняется при разных обращениях к серверу, в то время как текст запроса остается постоянным. Это переменные запроса. В языке GraphQL статическая типизация, что позволяет проверять значения переменных. В данной части объявляются типы переменных.

Переменные передаются отдельно от текста запроса в формате, принятом на транспортном уровне. В современных реализациях GraphQL обычно используется JSON. Вот как может выглядеть объект с переменными для показанного ранее запроса:


image
Рис. Пример объекта с переменными.


Как видно, ключ совпадает с названием, указанным в описании переменных. Значение взято из перечислимого типа Episode.


  • Переменные (Variables). Словарь значений, сопутствующий операции GraphQL. Содержит динамические параметры операции.

Еще одно базовое понятие не часто упоминается, но важно при обсуждении технических аспектов GraphQL – чем является то, что заключено в фигурные скобки?


image
Термин выборка (selection set) постоянно встречается в спецификации GraphQL. Именно с ним связана рекурсивная природа GraphQL, в которой возможны вложенные запросы.


  • Выборка (Selection set). Набор полей, запрашиваемых в операции или внутри другого поля. Для поля необходимо указать выборку, если поле возвращает объектный тип данных. Напротив, для скалярных полей типа Int и String не допускается указывать выборку.

Фрагменты


Фрагменты приносят еще больше возможностей в GraphQL. Вместе с тем приходя новые понятия.


  • Определение фрагмента (Fragment definition). Часть документа GraphQL, описывающая фрагмент GraphQL. Также называется именованным фрагментом (named fragment) в противоположность встроенному фрагменту (inline fragment), о котором будет сказано ниже.

image


  • Имя фрагмента (Fragment name). У каждого фрагмента уникальное в пределах документа имя. Оно используется для ссылки на фрагмент в операции или в другом фрагменте. Это имя, так же как имя операции, удобно использовать для логирования на сервере. Поэтому рекомендуется давать понятные имена, говорящие о назначении фрагмента. Если понадобится оптимизировать запросы, правильно подобранное имя облегчает поиск места в коде, где задан фрагмент.
  • Применимость к типу (Type condition). В отличие от операции GraphQL, которая всегда начинается с одного из типов: query, mutation или subscription, – фрагмент может быть использован в разных выборках. Чтобы фрагмент можно было сам по себе проверить на соответствие схеме, указывается пользовательский тип данных, к которому применим фрагмент.

Использование фрагментов в операциях


Фрагменты не особо полезны вне операций. Возможны два способа вставки фрагментов, как показано ниже.


image
Рис. Два типа фрагментов в запросе.


  • Развертка фрагмента (Fragment spread). Чтобы вставить фрагмент в операцию или в другой фрагмент, указывается перед названием фрагмента. Это называется разверткой. Она может присутствовать в выборке, которая применяется к тому же типу что и фрагмент.
  • Встроенный фрагмент (Inline fragment). Добавляет поля в выборку в зависимости от типа, к которому эта выборка применяется. При этом не создается внешнее определение фрагмента. Встроенный фрагмент подобен именованному, но задается в самом запросе. Отличие от именованного фрагмента в том, что не обязательно указывать тип данных. Чаще такие фрагменты используют вместе с директивами, как будет показано далее.

Директивы


С помощью директив реализуются дополнительные функции сервера GraphQL. Директивы не влияют на результирующие значения, но могут влиять на состав возвращаемых данных и, возможно, на то, как они получены. Директивы можно встретить почти в любом месте запроса, но в данной статье упоминаются только директивы skip и include, которые определены в текущей спецификации GraphQL.


image


Рис. Показанные конструкции вряд ли встречаются в одном запрос, но их удобно разом продемонстрировать в таком виде.


На рисунке – не связанные между собой примеры того, где можно использовать директивы skip и include. Они задают условия исполняемому модулю GraphQL игнорировать поля и не включать их значения в результат. Синтаксис директив открытый, и с их помощью разные реализации GraphQL могут добавлять новые возможности, не сильно усложняя разбор и выполнение запросов.


  • Директивы (Directives). Аннотации полей, фрагментов и операций, влияющие на их выполнение и возврат результатов.
  • Аргументы директив (Directive arguments). Имеют тот же смысл, как аргументы полей, но обрабатываются в исполняемом модуле GraphQL, а не передаются в функции-обработчики полей.

Включайтесь в обсуждение


Важное достоинство GraphQL – наличие универсального языка, с помощью которого можно описывать получение данных. Теперь у вас есть джентельменский набор терминов для обсуждения GraphQL, например в рамках продолжающейся дискуссии о подписках GraphQL.


В этой статье мы коснулись лишь части спецификации GraphQL, которая посвящена языку запросов. В следующих статьях мы, возможно, рассмотрим термины, в которых описывается схема GraphQL.


Хотите использовать технолоии GraphQL в повседневной работе? У нас есть различные вакансии на frontend, backend и open source!


Перевод статьи. Автор оригинала Sashko Stubailo

Tags:
Hubs:
+17
Comments 1
Comments Comments 1

Articles