- Время перевода документа: 2019/март/21 марта
- Переводчик: He Ruifeng (глубоко использовал GraqhQL)
- Цель: дать более приземленное китайское описание плюс: другие переводы слишком плохи
! Добро пожаловать, чтобы написать переводчику, чтобы обсудить вопросы, связанные с GraphQL!
Schemas and Types
В этой статье вы узнаете все подробности о системе типов GraphQL и о том, как она описывает, какие данные можно запрашивать. Поскольку GraphQL можно использовать в любой серверной среде и языке программирования, давайте оставим в стороне детали реализации GraphQL и сосредоточимся на основных концепциях.
Type System
Если вы видели запросы GraphQL, то знаете, что язык запросов GraphQL в основном запрашивает указанные поля объекта. Например
- query
{ hero { name appearsIn } }
- result
{ "data": { "hero": { "name": "R2-D2", "appearsIn": ["NEWHOPE","EMPIRE","JEDI"] } } }
- Начнем со специального «корневого» объекта
- существуетheroвыбор на месте
- дляheroВозвращаемый объект, мы выбираемnameа такжеappearsInполе
Поскольку запросы и результаты GraphQL точно соответствуют структуре, вы можете предсказать, какие данные вернет сервер, не заботясь о том, как сервер их реализует. Но полезно иметь точное описание данных, которые нам нужны, и определять, какие поля мы можем запрашивать? Какой объект будет возвращен? Какие поля доступны в дочерних объектах? Вот что делают схемы.
Каждый сервис GraphQL определяет набор типов, которые полностью описывают набор данных, к которым вы можете получить доступ. Затем, когда запрос получен, запрос проверяется и выполняется на основе схемы.
Type language
Службы GraphQL могут быть реализованы на любом языке, поскольку мы не полагаемся на синтаксис определенного языка программирования, такого как JavaScript, для объяснения схем GraphQL, мы определим наш собственный простой язык —"GraphQL schema language", который похож на язык QL, что позволяет нам хорошо взаимодействовать со схемами GraphQL.
Object types and fields
GraphQL schemaСамыми основными компонентами являютсяobject types, который определяет, какие объекты и подполя вы можете получить от серверной службы. Например:
type Character {
name: String!
appearsIn: [Episode!]!
}
Язык очень удобочитаемый, но давайте рассмотрим детали, чтобы сохранить базовое понимание терминологии.
- Characterэто GraphQLObject Type, указывая на то, что этот объект имеет определенные поля, большинство типов в вашей схемеObject Type
- nameа такжеappearsInдаCharactertype, что означает, что в запросе GraphQL при манипулировании типом Character можно использовать только name и visibleIn.
- Stringявляется одним из встроенных скалярных типов, который разрешается в один скалярный объект и не имеет дополнительных параметров. Мы подробно обсудим позже
- String!Указывает, что это поле является обязательным, то есть когда вы инициируете запрос GraphQL, поле должно иметь значение.На языке типов мы используем восклицательный знак для его идентификации.
- [Эпизод!]!Episode objects, и это непустой массив, и массив должен быть передан при запросе поля появления в, и все данные в данных должны быть типа Эпизод.
Теперь вы знаете, как выглядит тип объекта GraphQL и как читать язык.
Arguments
КаждыйGraphQL object typeможет иметь параметры, например:
type Starship {
id: ID!
name: String!
length(unit: LengthUnit = METER): Float
}
Каждый параметр имеет имя. В отличие от функций JavaScript и Python, которые получают упорядоченный набор параметров, параметры в GraphQL передаются по имени.В приведенном выше примереlengthПоле имеет определенный параметрunit.
Параметр может быть обязательным или необязательным.Когда параметр является необязательным, мы заранее определяем значение по умолчанию - если параметр единицы измерения не передает значение, он будет использовать значение по умолчанию METER.
The Query and Mutation types
Наличие двух типов в вашей схеме очень особенное
schema {
query: Query
mutation: Mutation
}
Каждый сервис GraphQL имеетquery type,mutation typeНе обязательно все, они особенные — определяйте запись каждого запроса GraphQl Когда вы видите следующий запрос
query {
hero {
name
}
droid(id: "2000") {
name
}
}
означает, что ваш сервис GraphQL должен иметьQuery typeсодержитhero and droidполе
type Query {
hero(episode: Episode): Character
droid(id: ID!): Droid
}
Мутации похожим образом, выMutation typeОпределите поля выше, эти поля являются точками входа при выполнении мутации.
Помните: типы Query и Mutation ничем не отличаются от обычных типов объектов, за исключением того, что они могут определять записи.
Scalar types
Тип объекта GraphQL имеет имена и поля, но в какой-то момент эти поля должны разрешаться в определенные данные. Например, возвращается поле появляется в [ Массив "NEWHOPE", "EMPIRE", "JEDI"].
GraqhQL имеет встроенную коллекцию скалярных типов.
- Int : 32-битное целое число со знаком
- Float : число с плавающей запятой со знаком двойной точности
- Строка: строка UTF-8.
- Boolean: true of false
- ID: представляет собой специальный идентификатор, часто используемый для получения определенного объекта или в качестве идентификатора ключа в кэше. Тип ID используется так же, как Stringserialize; но когда мы определяем идентификатор, нам не нужно, чтобы он был читабельным
В большинстве реализаций службы GraphQL часто используется специальный настраиваемый скалярный тип, например, мы можем определить тип даты:
scalar Date
Тогда мы можем определить, как идтиserialize, десериализовать и проверить этот тип. Например, вы можете указать, что тип Date сериализуется в целочисленную отметку времени.
Enumeration types
Эти типы, также называемые перечислениями, представляют собой специальные скалярные типы, которые можно выбрать только из определенного набора значений. Эффект от этого
- Убедитесь, что параметры этого типа могут иметь только определенные значения.
- Во всей системе типов всегда есть только ограниченное количество возможных значений для этого поля
Вот как выглядит определение перечисления на языке схем GraphQL?
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
Это предполагает это везде, где вы используетеtype Episode, мы думаем, что он имеет только вышеупомянутые значения.
Примечание. Сервисы GraphQL, реализованные на разных языках, имеют собственный способ обработки типов перечисления. В языке, который рассматривает перечисления как объекты первого класса, такая реализация может использовать преимущества вышеуказанных свойств. Но в таких языках, как JavaScript, которые не поддерживают многоточечные перечисления, их значения могут быть сопоставлены с рядом целочисленных наборов. Тогда клиент не будет знать этих деталей, и клиент будет работать полностью по строковому имени значения перечисления.
Lists and Non-Null
К этому абзацу относится много ерунды, а очки знаний можно получить из предыдущих рассуждений. Переводить не буду, на самом деле можете пропустить. Если вы беспокоитесь, вы можете обратиться к исходному тексту
Interfaces
Как и другие системы типов, GraphQL также поддерживает интерфейсы. Интерфейс — это абстрактный тип, который содержит определенный набор полей. Возьмем пример
Заранее определите интерфейс и дождитесь реализации других типов,
interface Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
}
Любой тип, реализующий Character, должен иметь указанные выше поля и параметры следующим образом.
type Human implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
# 上面是Character接口的
starships: [Starship]
totalCredits: Int
}
type Droid implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
# 上面是Character接口的
primaryFunction: String
}
В дополнение к полям, определенным в интерфейсе Персонажа, Человек и Дроид также могут иметь свои собственные определенные поля.
Интерфейсы полезны, когда вы хотите вернуть объект или диапазон типов объектов.
query HeroForEpisode($ep: Episode!) {
hero(episode: $ep) {
name
... on Droid {
primaryFunction
}
}
}
// 变量
{
"ep": "JEDI"
}
Поле героя определено заранее и возвращает тип Персонажа, а во внутренней реализации только Человек или Дроид реализуют тип Персонажа, поэтому для встроенных полей типа Персонажа, таких как имя, вы можете его получить. напрямую, но другие уровни реализации являются специфическими. Поля, такие как основная функция на Droid, должны быть получены с использованием встроенных фрагментов.
Learn more about this in the inline fragments section in the query guide.
Примечание переводчика: интерфейсы используются как абстрактные типы, и все типы, реализующие интерфейсы, имеют общедоступные поля.
Union types
Типы объединения очень похожи на типы интерфейса, но не определяют общие поля между типами.
union SearchResult = Human | Droid | Starship
Всякий раз, когда мы возвращаем тип SearchResult, мы можем получить три вышеуказанных типа.Обратите внимание, что тип объединения должен состоять из фактического типа объекта и не может состоять из других типов объединения или интерфейсов.
В этом примере, если вы запрашиваете поле, которое возвращаетSerchResult union type, также необходимо использовать встроенный фрагмент
- query
{ search(text: "an") { __typename ... on Human { name height } ... on Droid { name primaryFunction } ... on Starship { name length } } }
- result
{
"data": {
"search": [
{
"__typename": "Human",
"name": "Han Solo",
"height": 1.8
},
{
"__typename": "Human",
"name": "Leia Organa",
"height": 1.5
},
{
"__typename": "Starship",
"name": "TIE Advanced x1",
"length": 9.2
}
]
}
}
__typenameПоле возвращает String , который используется в качестве идентификатора, чтобы отличить его от других типов данных.
И в этом примере, посколькуHumanа такжеDroidВсе они имеют общий интерфейс (Character), и вы можете напрямую запрашивать их общедоступные поля, а не повторно запрашивать их.
{
search(text: "an") {
__typename
... on Character {
name
}
... on Human {
height
}
... on Droid {
primaryFunction
}
... on Starship {
name
length
}
}
}
Обратите внимание здесьnameсуществуетStarshipдолжен быть указан, иначе **name ** не будет отображаться в результатах запроса, так как он не использует тот же интерфейс.
Input types
До сих пор мы обсуждали только передачу скалярных значений, таких как перечисления или строки, в качестве аргументов. Но вы можете передавать сложные объекты в качестве параметров. это вmutationОчень полезно тем, что вы можете передать большой объект на сервер. существуетGraphQL schema languageсередина,input typeи другие обычныеobject typesТо же самое, но вместо ключевого слова type используйтеinputкак ключевое слово.
input ReviewInput {
stars: Int!
commentary: String
}
Ниже приведен пример использования
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
// 变量
{
"ep": "JEDI",
"review": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
// 返回的数据
{
"data": {
"createReview": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
}
input object typeПоля также могут указывать на другиеinput object type(Примечание переводчика: объекты вложены друг в друга, чтобы сформировать более сложную структуру параметров), но не путайте тип ввода/вывода.input object typeПередача параметров не поддерживается для полей.
! ! ! Полный текст готов! ! ! Здесь все есть, переводить не просто, ставьте пожалуйста свои 👍! Это будет моей мотивацией продолжать предоставлять качественные статьи
Также переведена документация клиента:nuggets.capable/post/684490…