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 esquema GraphQL é a base de qualquer implementação de servidor de GraphQL. Cada API GraphQL é definida por um único esquema que contém tipos e campos que descrevem como os dados das solicitações serão preenchidos. Os dados que fluem pela sua API e as operações realizadas devem ser validados com base no esquema.
O sistema do tipo GraphQL
AWS AppSync permite que você defina e configure esquemas do GraphQL. A seção a seguir descreve como criar esquemas do GraphQL do zero usando AWS AppSync os serviços da.
Estruturar um esquema do GraphQL
dica
Consulte a seção Schemas antes de continuar.
O GraphQL é uma ferramenta poderosa para implementar serviços de API. A descrição (em tradução livre) no site do GraphQL
“O GraphQL é uma linguagem de consulta APIs e um tempo de execução para atender essas consultas com seus dados existentes. O GraphQL fornece uma descrição completa e compreensível dos dados em sua API, dá aos clientes o poder de pedir exatamente o que precisam e nada mais, facilita a evolução ao APIs longo do tempo e habilita ferramentas poderosas para desenvolvedores. “
Esta seção aborda a primeira parte da sua implementação do GraphQL, o esquema. De acordo com a citação acima, um esquema “fornece uma descrição completa e clara dos dados em sua API”. Em outras palavras, um esquema do GraphQL é uma representação textual dos dados, das operações e das relações entre eles referentes ao seu serviço. O esquema é considerado o principal ponto de entrada para a implementação do serviço do GraphQL. Não é de surpreender que muitas vezes seja uma das primeiras coisas que você faz em seu projeto. Consulte a seção Schemas antes de continuar.
Citando a seção Schemas, os esquemas do GraphQL são escritos em Schema Definition Language (SDL). O SDL é composto por tipos e campos com uma estrutura estabelecida:
-
Tipos: os tipos são como o GraphQL define a forma e o comportamento dos dados. O GraphQL é compatível com uma infinidade de tipos que serão explicados ainda nesta seção. Cada um dos tipos definidos em seu esquema terá um escopo próprio. Dentro do escopo, um ou mais campos vão apresentar um valor ou lógica que será usada em seu serviço do GraphQL. Os tipos têm muitas funções diferentes, sendo as mais comuns objetos ou escalares (tipos de valores primitivos).
-
Campos: os campos existem dentro do escopo de um tipo e contêm o valor solicitado do serviço do GraphQL. Eles são muito semelhantes às variáveis de outras linguagens de programação. A forma dos dados que você define em seus campos determinará como os dados são estruturados em uma operação de solicitação/resposta. Isso permite que os desenvolvedores prevejam o que será retornado sem saber como o back-end do serviço é implementado.
Os esquemas mais simples conterão três categorias de dados:
-
Raízes do esquema: as raízes definem os pontos de entrada do seu esquema. Elas apontam para os campos que realizarão alguma operação nos dados, como adicionar, excluir ou modificar algo.
-
Tipos: esses são tipos básicos usados para representar o formato dos dados. Eles são muito semelhantes a objetos ou representações abstratas de algo com características definidas. Por exemplo, você pode criar um objeto
Person
que represente uma pessoa em um banco de dados. As características de cada pessoa serão definidas dentro dePerson
como campos. Eles podem ser qualquer dado da pessoa, como o nome, a idade, o emprego, o endereço etc. -
Tipos de objetos especiais: esses são os tipos que definem o comportamento das operações em seu esquema. Cada tipo de objeto especial é definido uma vez por esquema. Eles são colocados primeiro na raiz do esquema e, em seguida, definidos no corpo do esquema. Cada campo em um tipo de objeto especial define uma única operação a ser implementada pelo seu solucionador.
Para entender melhor, imagine que você esteja criando um serviço que armazena dados de autores de livros e suas obras. Cada autor tem um nome e uma série de livros escritos. Cada livro tem um nome e uma lista de autores associados. Além disso, queremos adicionar ou recuperar livros e autores. Uma representação UML simples desse relacionamento pode ser como esta:

No GraphQL, as entidades Author
e Book
representam dois tipos diferentes de objetos em seu esquema:
type Author {
}
type Book {
}
Author
contém authorName
e Books
, enquanto Book
contém bookName
e Authors
. Eles podem ser representados como os campos dentro do escopo de seus tipos:
type Author {
authorName: String
Books: [Book]
}
type Book {
bookName: String
Authors: [Author]
}
Como você pode ver, as representações de tipo estão muito próximas do diagrama. No entanto, os métodos são os pontos mais complexos. Eles serão colocados em um dos poucos tipos de objetos especiais como um campo. A categorização como objeto especial depende do comportamento dele. O GraphQL contém três tipos fundamentais de objetos especiais: consultas, mutações e assinaturas. Para obter mais informações, consulte Special objects.
Como getAuthor
e getBook
estão solicitando dados, eles serão colocados em um tipo de objeto especial de Query
:
type Author {
authorName: String
Books: [Book]
}
type Book {
bookName: String
Authors: [Author]
}
type Query {
getAuthor(authorName: String): Author
getBook(bookName: String): Book
}
As operações são vinculadas à consulta, que por sua vez está vinculada ao esquema. Adicionar uma raiz de esquema definirá o tipo de objeto especial (neste caso, Query
) como um dos seus pontos de entrada. Isso pode ser feito usando a palavra-chave schema
:
schema {
query: Query
}
type Author {
authorName: String
Books: [Book]
}
type Book {
bookName: String
Authors: [Author]
}
type Query {
getAuthor(authorName: String): Author
getBook(bookName: String): Book
}
Analisando os últimos dois métodos, addAuthor
e addBook
estão adicionando informações ao seu banco de dados para que sejam definidos em um tipo de objeto especial Mutation
. No entanto, na página Tipos, não é permitido usar entradas que fazem referência direta a objetos, porque são tipos de saída. Nesse caso, não podemos usar Author
nem Book
, então precisamos criar um tipo de entrada com os mesmos campos. Neste exemplo, adicionamos AuthorInput
e BookInput
, que aceitam os mesmos campos de seus respectivos tipos. Em seguida, criamos nossa mutação usando as entradas como nossos parâmetros:
schema {
query: Query
mutation: Mutation
}
type Author {
authorName: String
Books: [Book]
}
input AuthorInput {
authorName: String
Books: [BookInput]
}
type Book {
bookName: String
Authors: [Author]
}
input BookInput {
bookName: String
Authors: [AuthorInput]
}
type Query {
getAuthor(authorName: String): Author
getBook(bookName: String): Book
}
type Mutation {
addAuthor(input: [BookInput]): Author
addBook(input: [AuthorInput]): Book
}
Vamos analisar o que acabamos de fazer:
-
Criamos um esquema com os tipos
Author
eBook
para representar nossas entidades. -
Adicionamos os campos contendo as características de nossas entidades.
-
Adicionamos uma consulta para recuperar essas informações do banco de dados.
-
Adicionamos uma mutação para manipular dados no banco de dados.
-
Adicionamos tipos de entrada para substituir nossos parâmetros de objeto na mutação para cumprir as regras do GraphQL.
-
Adicionamos a consulta e a mutação ao nosso esquema raiz para que a implementação do GraphQL identifique a localização do tipo raiz.
Como você pode notar, o processo de criação de um esquema usa muitos conceitos da modelagem de dados (especialmente da modelagem de banco de dados) em geral. Podemos dizer que o esquema se ajusta à forma dos dados da fonte. Ele também serve como o modelo que o solucionador implementará. Nas seções a seguir, você aprenderá como criar um esquema usando várias ferramentas e AWS serviços suportados.
nota
Os exemplos nas seções a seguir não devem ser executados em uma aplicação real. Eles apenas mostram os comandos para que você crie suas próprias aplicações.
Criar esquemas
Seu esquema estará em um arquivo chamadoschema.graphql
. AWS AppSync permite que os usuários criem novos esquemas para seu APIs GraphQL usando vários métodos. Neste exemplo, criaremos uma API em branco junto com um esquema em branco.
-
Faça login no AWS Management Console e abra o AppSyncconsole
. -
No Painel, escolha Criar API.
-
Em Opções de API, escolha GraphQL APIs, Design from scratch e Next.
-
Para o nome da API, troque o nome pré-preenchido algo que seja necessário para a aplicação.
-
Para obter detalhes de contato, você pode inserir um ponto de contato para identificar um gerente para a API. Esse é um campo opcional.
-
Em Configuração da API privada, é possível habilitar os atributos da API privada. Uma API privada só pode ser acessada de um endpoint da VPC (VPCE) configurado. Para obter mais informações, consulte Privado APIs.
Não recomendamos habilitar esse atributo para este exemplo. Após analisar suas entradas, selecione Próximo.
-
-
Em Criar um tipo de GraphQL, você pode criar uma tabela do DynamoDB para usar como fonte de dados ou ignorar e fazer isso depois.
Para este exemplo, escolha Criar recursos do GraphQL mais tarde. Vamos criar um recurso em uma seção separada.
-
Revise suas entradas e selecione Criar API.
-
-
Você estará no painel da sua API específica. É possível identificar o nome da API na parte superior do painel. Se esse não for o caso, você pode selecionar APIsna barra lateral e escolher sua API no APIs painel.
-
Na barra lateral abaixo do nome da sua API, escolha Esquema.
-
-
Você pode configurar seu arquivo
schema.graphql
no editor de esquemas. Ele pode estar vazio ou preenchido com tipos gerados a partir de um modelo. À direita, você tem a seção Solucionadores para anexar solucionadores aos campos do esquema. Não examinaremos os solucionadores nesta seção.
Adicionar tipos aos esquemas
Agora que você adicionou seu esquema, pode começar a adicionar os tipos de entrada e saída. Os tipos aqui não devem ser usados em código real; eles são apenas exemplos para ajudar você a entender o processo.
Primeiro, vamos criar um tipo de objeto. No código real, não é necessário começar com esses tipos. Você pode criar o tipo que preferir a qualquer momento, desde que siga as regras e a sintaxe do GraphQL.
nota
As próximas seções usarão o editor de esquemas, portanto, mantenha-o aberto.
-
Você pode criar um tipo de objeto usando a palavra-chave
type
junto com o nome do tipo:type
Type_Name_Goes_Here
{}Dentro do escopo do tipo, você pode adicionar campos que representam as características do objeto:
type
Type_Name_Goes_Here
{ # Add fields here }Veja um exemplo abaixo:
type
Obj_Type_1
{id: ID! title: String date: AWSDateTime
}nota
Nesta etapa, adicionamos um tipo de objeto genérico com um campo obrigatório
id
armazenado comoID
, um campotitle
armazenado comoString
, e um campodate
armazenado comoAWSDateTime
. Para visualizar uma lista de tipos e campos e o que eles fazem, consulte Schemas. Para visualizar uma lista de escalares e o que eles fazem, consulte a Type reference.
O tipo de objetoAWSDateTime
adição aos escalares básicos do GraphQL. Qualquer campo que termine com um ponto de exclamação é um campo obrigatório.
O tipo de escalar ID
é um identificador exclusivo que pode ser String
ou Int
. É possível controlar isso nos modelos de mapeamento do solucionador para atribuição automática.
Há semelhanças entre tipos de objetos especiais de Query
e tipos de objetos “comuns”, como no exemplo acima, pois ambos usam a palavra-chave type
e são considerados objetos. No entanto, para os tipos de objetos especiais (Query
, Mutation
eSubscription
), o comportamento deles é muito diferente porque eles são expostos como pontos de entrada da sua API. Eles também priorizam a modelagem de operações em vez dos dados. Para obter mais informações, consulte The query and mutation types
No tópico dos tipos de objetos especiais, a próxima etapa pode ser adicionar um ou mais deles para realizar operações nos dados modelados. Em um cenário real, todo esquema do GraphQL deve ter pelo menos um tipo de consulta-raiz para solicitar dados. Você pode pensar na consulta como um dos pontos de entrada (ou endpoints) do seu servidor do GraphQL. Vamos adicionar uma consulta como exemplo.
-
Para criar uma consulta, basta adicioná-la ao arquivo do esquema como qualquer outro tipo. Uma consulta exigiria um tipo de
Query
e uma entrada na raiz como esta:schema { query:
Name_of_Query
} typeName_of_Query
{ # Add field operation here }Observe que
Name_of_Query
em um ambiente de produção simplesmente será chamadoQuery
na maioria dos casos. Recomendamos manter esse valor baixo. Dentro do tipo de consulta, você pode adicionar campos. Cada campo executará uma operação na solicitação. Como resultado, a maioria desses campos, se não todos, serão anexados a um solucionador. No entanto, não vamos abordar esse assunto nesta seção. Em relação ao formato da operação do campo, ela pode ser como esta:Name_of_Query(params): Return_Type
# version with paramsName_of_Query: Return_Type
# version without paramsVeja um exemplo abaixo:
schema { query: Query } type Query {
getObj: [Obj_Type_1]
} type Obj_Type_1 { id: ID! title: String date: AWSDateTime }nota
Nesta etapa, adicionamos um tipo de
Query
e o definimos na raiz do nossoschema
. Nosso tipo deQuery
definiu um campogetObj
que retorna uma lista de objetosObj_Type_1
. EsseObj_Type_1
é o objeto da etapa anterior. No código de produção, suas operações de campo normalmente trabalharão com dados moldados por objetos comoObj_Type_1
. Além disso, campos comogetObj
normalmente terão um solucionados para executar a lógica de negócios. Isso será abordado em outra seção.Como observação adicional, adiciona AWS AppSync automaticamente uma raiz do esquema durante as exportações, então, tecnicamente, você não precisa adicioná-la diretamente ao esquema. Nosso serviço processará esquemas duplicados de maneira automática. Essa é uma prática recomendada.
Mostramos um exemplo de criação de objetos comuns e objetos especiais (consultas). Também abordamos como eles se interconectam para descrever dados e operações. Pode haver esquemas apenas com a descrição dos dados e uma ou mais consultas. No entanto, gostaríamos de adicionar outra operação para incluir dados na fonte de dados. Adicionaremos outro tipo de objeto especial chamado Mutation
que modifica os dados.
-
Uma mutação será chamada de
Mutation
. Como aQuery
, as operações de campo emMutation
descrevem uma operação e serão anexadas a um solucionador. Além disso, precisamos defini-lo na raiz doschema
porque é um tipo de objeto especial. Veja um exemplo de mutação abaixo:schema {
mutation: Name_of_Mutation
} typeName_of_Mutation
{ # Add field operation here }Uma mutação típica será listada na raiz como uma consulta. A mutação é definida usando a
type
palavra-chave junto com o nome.Name_of_Mutation
normalmente serão chamadosMutation
, por isso recomendamos que continue assim. Cada campo também executará uma operação. Em relação ao formato da operação do campo, ela pode ser como esta:Name_of_Mutation(params): Return_Type # version with params Name_of_Mutation: Return_Type # version without params
Veja um exemplo abaixo:
schema { query: Query
mutation: Mutation
} type Obj_Type_1 { id: ID! title: String date: AWSDateTime } type Query { getObj: [Obj_Type_1] } type Mutation {addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
}nota
Nesta etapa, adicionamos um tipo de
Mutation
com um campoaddObj
. Vamos resumir o que esse campo faz:addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
O
addObj
usa o objetoObj_Type_1
para realizar uma operação. Isso é evidente ao observar os campos, mas a sintaxe prova isso no tipo de retorno: Obj_Type_1
. EmaddObj
, os camposid
,title
edate
do objetoObj_Type_1
como parâmetros. Como podemos notar, ela se parece muito com uma declaração de método. No entanto, ainda não descrevemos o comportamento do nosso método. Conforme mencionado anteriormente, o esquema só existe para definir quais serão os dados e as operações e não a forma como operam. A implementação da lógica de negócios real será abordada quando criarmos nossos primeiros solucionadores.Depois de concluir o esquema, há uma opção para exportá-lo como um arquivo
schema.graphql
. No Editor de esquemas, você pode escolher Exportar esquema para fazer download do arquivo em um formato compatível.Como observação adicional, adiciona AWS AppSync automaticamente uma raiz do esquema durante as exportações, então, tecnicamente, você não precisa adicioná-la diretamente ao esquema. Nosso serviço processará esquemas duplicados de maneira automática. Essa é uma prática recomendada.
Considerações opcionais: usar enumerados como status
Neste ponto, você já sabe como criar um esquema básico. No entanto, há muitos elementos que você pode adicionar para aumentar a funcionalidade do esquema. Uma coisa comum encontrada nas aplicações é o uso de enumerados como status. Você pode usar um enumerado para aplicar um valor específico de um conjunto de valores a ser escolhido quando chamado. Isso é bom para elementos que não mudarão drasticamente por longos períodos. Hipoteticamente falando, poderíamos adicionar um enumerado que retorna o código de status ou string na resposta.
Como exemplo, vamos supor que estamos criando uma aplicação de mídia social que armazena os dados de postagem de um usuário no back-end. Nosso esquema contém um tipo de Post
que representa os dados de uma postagem individual:
type Post {
id: ID!
title: String
date: AWSDateTime
poststatus: PostStatus
}
Nossa Post
conterá um único id
, um title
, uma date
de postagem e um enumerado chamado de PostStatus
, que representa o estado da postagem conforme ela é processada pela aplicação. Para nossas operações, teremos uma consulta que retornará todos os dados da postagem:
type Query {
getPosts: [Post]
}
Também teremos uma mutação que adiciona postagens à fonte de dados:
type Mutation {
addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}
Analisando nosso esquema, o enumerado PostStatus
pode ter vários status. É possível termos os três estados básicos chamados de success
(postagem processada com sucesso), pending
(postagem sendo processada) e error
(postagem que não foi processada). Para adicionar o enumerado, podemos fazer o seguinte:
enum PostStatus {
success
pending
error
}
O esquema completo pode ser semelhante a este:
schema {
query: Query
mutation: Mutation
}
type Post {
id: ID!
title: String
date: AWSDateTime
poststatus: PostStatus
}
type Mutation {
addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}
type Query {
getPosts: [Post]
}
enum PostStatus {
success
pending
error
}
Se um usuário adicionar uma Post
à aplicação, a operação addPost
será chamada para processar esses dados. À medida que o solucionador anexado à addPost
processa os dados, ele vai atualizar o poststatus
continuamente com o status da operação. Quando consultado, a Post
vai mostrar o status final dos dados. Aqui só descrevemos como queremos que os dados funcionem no esquema. Fazemos muitas suposições sobre a implementação de nossos solucionadores, que implementarão a lógica comercial real para lidar com os dados e atender à solicitação.
Considerações opcionais: assinaturas
As assinaturas em AWS AppSync são invocadas como resposta a uma mutação. Isso pode ser configurado com um tipo Subscription
e diretiva @aws_subscribe()
no esquema para indicar quais mutações invocam uma ou mais assinaturas. Consulte Real-time data para obter mais informações sobre como configurar assinaturas.
Considerações opcionais: relações e paginação
Suponha que você tenha um milhão de Posts
armazenadas em uma tabela do DynamoDB e queira retornar alguns desses dados. No entanto, o exemplo de consulta fornecido acima retorna todas as postagens. Não é fácil buscar tudo isso sempre que fizer uma solicitação. O melhor é paginar
-
No campo
getPosts
, adicione dois argumentos de entrada:nextToken
(iterador) elimit
(limite de iteração). -
Adicione um novo tipo de
PostIterator
contendoPosts
(isso recupera a lista de objetosPost
) e camposnextToken
(iterador). -
Altere
getPosts
para que retornePostIterator
, não uma lista de objetosPost
.
schema {
query: Query
mutation: Mutation
}
type Post {
id: ID!
title: String
date: AWSDateTime
poststatus: PostStatus
}
type Mutation {
addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}
type Query {
getPosts(limit: Int, nextToken: String): PostIterator
}
enum PostStatus {
success
pending
error
}
type PostIterator {
posts: [Post]
nextToken: String
}
O tipo PostIterator
permite que você retorne parte da lista de objetos de Post
e um nextToken
para obter a próxima parte. Em PostIterator
, há uma lista de itens da Post
([Post]
) que é retornada com um token de paginação (nextToken
). Em AWS AppSync, isso seria conectado ao Amazon DynamoDB por meio de um resolvedor e gerado automaticamente como um token criptografado. Isso converte o valor do argumento limit
no parâmetro maxResults
e o argumento nextToken
no parâmetro exclusiveStartKey
. Para ver exemplos e exemplos de modelos integrados no AWS AppSync console, consulte Referência do Resolver (JavaScript).