As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
O GraphQL é compatível com muitos tipos diferentes. Como você viu na seção anterior, os tipos definem a forma ou o comportamento dos seus dados. Eles são os blocos de construção fundamentais de um esquema do GraphQL.
Os tipos podem ser categorizados em entradas e saídas. As entradas são tipos que podem ser transmitidos como argumento para os tipos de objetos especiais (Query
, Mutation
, etc.), enquanto os tipos de saída são usados estritamente para armazenar e retornar dados. Uma lista de tipos e suas categorizações estão listadas abaixo:
-
Objetos: um objeto contém campos que descrevem uma entidade. Por exemplo, um objeto pode ser algo como um
book
com campos descrevendo suas características, comoauthorName
,publishingYear
, etc. Eles são estritamente tipos de saída. -
Escalares: esses são tipos primitivos como int, string, etc. Normalmente, eles são atribuídos a campos. Usando o campo
authorName
como exemplo, ele pode ser atribuído ao escalarString
para armazenar um nome como “John Smith”. Escalares podem ser do tipo de entrada e saída. -
Entradas: as entradas permitem que você transmita um grupo de campos como argumento. Elas são estruturadas de forma muito semelhante aos objetos, mas podem ser passadas como argumentos para objetos especiais. As entradas permitem que você defina escalares, enums e outras entradas em seu escopo. As entradas só podem ser tipos de entrada.
-
Objetos especiais: objetos especiais realizam operações de mudança de estado e fazem a maior parte do trabalho pesado do serviço. Há três tipos de objetos especiais: consulta, mutação e assinatura. As consultas normalmente buscam dados; as mutações manipulam dados; as assinaturas abrem e mantêm uma conexão bidirecional entre clientes e servidores para comunicação constante. Objetos especiais não são de entrada nem saída, dada sua funcionalidade.
-
Enums: enums são listas predefinidas de valores legais. Se você chamar um enum, seus valores só poderão ser definidos em seu escopo. Por exemplo, se você tivesse uma enumeração chamada
trafficLights
representando uma lista de sinais de trânsito, ela poderia ter valores comoredLight
egreenLight
, mas nãopurpleLight
. Um semáforo real terá um limite de sinais, então você pode usar o enum para defini-los e forçá-los a serem os únicos valores legais ao fazer referência atrafficLight
. Escalares podem ser do tipo de entrada e saída. -
Uniões/interfaces: as uniões permitem que você retorne uma ou mais coisas em uma solicitação, dependendo dos dados solicitados pelo cliente. Por exemplo, se você tivesse um tipo
Book
com umtitle
campo e um tipoAuthor
com um camponame
, você poderia criar uma união entre os dois tipos. Se seu cliente quisesse consultar um banco de dados para a frase “Júlio César”, a união poderia retornar Júlio César (a peça de William Shakespeare) dotitle
Book
e Júlio César (o autor de Commentarii de Bello Gallico) doname
Author
. As uniões só podem ser tipos de saída.As interfaces são conjuntos de campos que os objetos devem implementar. Isso é um pouco semelhante às interfaces em linguagens de programação como Java, nas quais você precisa implementar os campos definidos na interface. Por exemplo, digamos que você tenha criado uma interface chamada
Book
que continha um campotitle
. Digamos que você tenha criado posteriormente um tipo chamadoNovel
que implementouBook
. SeuNovel
teria que incluir um campotitle
. No entanto, seuNovel
também pode incluir outros campos que não estão na interface, comopageCount
ouISBN
. As interfaces só podem ser tipos de saída.
As seções a seguir explicarão como cada tipo funciona no GraphQL.
Objetos
Os objetos do GraphQL são o tipo principal que você verá no código de produção. No GraphQL, você pode pensar em um objeto como um agrupamento de campos diferentes (semelhantes às variáveis em outras linguagens), e cada campo é definido por um tipo (normalmente um escalar ou outro objeto) que pode conter um valor. Os objetos representam uma unidade de dados que pode ser recuperada/manipulada a partir da implementação do serviço.
Os tipos de objetos são declarados usando a palavra-chave Type
. Vamos modificar um pouco nosso exemplo de esquema:
type Person {
id: ID!
name: String
age: Int
occupation: Occupation
}
type Occupation {
title: String
}
Os tipos de objeto aqui são Person
e Occupation
. Cada objeto tem seus próprios campos com seus próprios tipos. Um atributo do GraphQL é a capacidade de definir campos como outros tipos. Você pode ver que o campo occupation
em Person
contém um tipo de objeto Occupation
. Podemos fazer essa associação porque o GraphQL está apenas descrevendo os dados e não a implementação do serviço.
Escalares
Os escalares são tipos essencialmente primitivos que contêm valores. Em AWS AppSync, há dois tipos de escalares: os escalares e AWS AppSync escalares padrão do GraphQL. Os escalares costumam ser usados para armazenar valores de campo em tipos de objetos. Os tipos padrão do GraphQL incluem Int
, Float
, String
,Boolean
e ID
. Vamos usar o exemplo anterior novamente:
type Person {
id: ID!
name: String
age: Int
occupation: Occupation
}
type Occupation {
title: String
}
Destacando os campos name
e title
e, ambos possuem um escalar String
, e Name
poderia retornar um valor de string como "John Smith
" e o título poderia retornar algo como "firefighter
”. Algumas implementações do GraphQL também oferecem suporte a escalares personalizados usando a palavra-chaveScalar
e implementando o comportamento do tipo. No entanto, atualmente o AWS AppSync não oferece suporte a escalares personalizados. Para obter uma lista de escalares, consulte Tipos de escalares no AWS AppSync.
Entradas
Devido ao conceito de tipos de entrada e saída, existem certas restrições ao transmitir argumentos. Os tipos que normalmente precisam ser transmitidos, principalmente objetos, são restritos. Você pode usar o tipo de entrada para ignorar essa regra. As entradas são tipos que contêm escalares, enums e outros tipos de entrada.
As entradas são definidas usando a palavra-chave input
:
type Person {
id: ID!
name: String
age: Int
occupation: Occupation
}
type Occupation {
title: String
}
input personInput {
id: ID!
name: String
age: Int
occupation: occupationInput
}
input occupationInput {
title: String
}
Como você pode ver, podemos ter entradas separadas que imitam o tipo original. Essas entradas geralmente serão usadas em suas operações de campo da seguinte forma:
type Person {
id: ID!
name: String
age: Int
occupation: Occupation
}
type Occupation {
title: String
}
input occupationInput {
title: String
}
type Mutation {
addPerson(id: ID!, name: String, age: Int, occupation: occupationInput): Person
}
Observe como ainda estamos transmitindo occupationInput
em vez de Occupation
para criar uma Person
.
Este é apenas um dos cenários para entradas. Elas não precisam copiar objetos 1:1 e, no código de produção, você provavelmente não as usará dessa forma. É uma prática recomendada aproveitar os esquemas do GraphQL definindo somente o que você precisa inserir como argumentos.
Além disso, as mesmas entradas podem ser usadas em várias operações, mas não recomendamos fazer isso. Preferencialmente, cada operação deve conter sua própria cópia exclusiva das entradas, caso os requisitos do esquema mudem.
Objetos especiais
O GraphQL reserva algumas palavras-chave para objetos especiais que definem parte da lógica de negócios de como seu esquema recuperará/manipulará dados. No máximo, pode haver uma de cada uma dessas palavras-chave em um esquema. Eles atuam como pontos de entrada para todos os dados solicitados que seus clientes executam no seu serviço GraphQL.
Objetos especiais também são definidos usando a palavra-chave type
. Embora sejam usados de forma diferente dos tipos de objetos comuns, sua implementação é muito semelhante.
As consultas são muito semelhantes às operações GET
, pois realizam uma busca somente para leitura para obter dados da sua fonte. No GraphQL, a Query
define todos os pontos de entrada para clientes que fazem solicitações em seu servidor. Sempre haverá um Query
em sua implementação do GraphQL.
Aqui estão os tipos Query
de objetos modificados que usamos em nosso exemplo de esquema anterior:
type Person {
id: ID!
name: String
age: Int
occupation: Occupation
}
type Occupation {
title: String
}
type Query {
people: [Person]
}
Nosso Query
contém um campo chamado people
que retorna uma lista de instâncias Person
da fonte de dados. Digamos que precisemos mudar o comportamento do nosso aplicativo e agora precisamos retornar uma lista somente das instâncias de Occupation
para algum propósito separado. Poderíamos simplesmente adicioná-lo à consulta:
type Query {
people: [Person]
occupations: [Occupation]
}
No GraphQL, podemos tratar nossa consulta como a única fonte de solicitações. Como você pode ver, isso é potencialmente muito mais simples do que RESTful implementações que podem usar endpoints diferentes para alcançar a mesma coisa (.../api/1/people
e). .../api/1/occupations
Supondo que tenhamos uma implementação de resolvedor para essa consulta, agora podemos realizar uma consulta real. Embora o tipo Query
exista, precisamos chamá-lo explicitamente para que ele seja executado no código do aplicativo. Isso pode ser feito usando a palavra-chave query
:
query getItems {
people {
name
}
occupations {
title
}
}
Como você pode ver, essa consulta é chamada getItems
e retorna people
(uma lista de objetos Person
) e occupations
(uma lista de objetos Occupation
). Em people
, estamos retornando somente o campo name
de cada Person
, enquanto retornamos o campo title
de cada Occupation
. A resposta pode ser semelhante a:
{
"data": {
"people": [
{
"name": "John Smith"
},
{
"name": "Andrew Miller"
},
.
.
.
],
"occupations": [
{
"title": "Firefighter"
},
{
"title": "Bookkeeper"
},
.
.
.
]
}
}
O exemplo de resposta mostra como os dados seguem a forma da consulta. Cada entrada recuperada é listada dentro do escopo do campo. people
e occupations
estão retornando itens como listas separadas. Embora isso seja útil, talvez seja mais conveniente modificar a consulta para retornar uma lista dos nomes e ocupações das pessoas:
query getItems {
people {
name
occupation {
title
}
}
Essa é uma modificação legal porque nosso tipo Person
contém um campo occupation
de tipo Occupation
. Quando listados no escopo de people
, retornamos cada um name
de Person
junto com os Occupation
associados por title
. A resposta pode ser semelhante a:
}
"data": {
"people": [
{
"name": "John Smith",
"occupation": {
"title": "Firefighter"
}
},
{
"name": "Andrew Miller",
"occupation": {
"title": "Bookkeeper"
}
},
.
.
.
]
}
}
Algo que não foi mencionado em nosso exemplo de esquema é o fato de que seus tipos de objetos especiais também devem ser definidos em um schema
raiz. Então, quando você exporta um esquema AWS AppSync, ele pode ter a seguinte aparência:
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
.
.
.
type Query {
# code goes here
}
type Mutation {
# code goes here
}
type Subscription {
# code goes here
}
Enumerações
Enumerações, ou enums, são escalares especiais que limitam os argumentos legais que um tipo ou campo pode ter. Isso significa que sempre que uma enum for definida no esquema, seu tipo ou campo associado será limitado aos valores da enum. As enums são serializadas como escalares de string. Observe que diferentes linguagens de programação podem lidar com enumerações do GraphQL de forma diferente. Por exemplo, não JavaScript tem suporte nativo para enum, portanto, os valores enum podem ser mapeados para valores int em vez disso.
As enums são definidas usando a palavra-chave enum
. Veja um exemplo abaixo:
enum trafficSignals {
solidRed
solidYellow
solidGreen
greenArrowLeft
...
}
Ao chamar o trafficLights
enum, os argumentos só podem ser solidRed
, solidYellow
, solidGreen
, etc. É comum usar enums para descrever coisas que têm um número distinto, mas limitado, de opções.
Uniões/Interfaces
Consulte Interfaces e uniões no GraphQL.