Menu Docs

Página inicial do DocsServiços Atlas App

Definir um Resolvedor Personalizado

Nesta página

  • Visão geral
  • Procedimento
  • Criar um novo revendedor personalizado
  • Definir o Nome do Campo do Resolvedor
  • Definir o tipo principal
  • Definir o Tipo de Entrada
  • Definir o tipo de carga útil
  • Definir a função Resolver
  • Salvar e distribuir o resolvedor
  • Exemplos de resolvedores personalizados
  • Cenário e esquemas
  • Resolvedor de query personalizada
  • Mutação personalizada
  • Propriedades computadas

Você pode definir resolvedores personalizados que estendem a GraphQL API para os casos de uso do seu aplicativo. Os resolvedores personalizados permitem definir novas operações de nível raiz que são mais complexas ou específicas do que os resolvedores de query e mutação gerados. Também é possível adicionar novos campos calculados a tipos de documento gerados que avaliam dinamicamente um resultado sempre que uma operação lê um documento do tipo estendido.

1

Na UI do App Services, clique em GraphQL na barra lateral de navegação e selecione a aba Custom Resolvers.

Clique no botão Add a Custom Resolver para abrir a tela de configuração de um novo resolvedor personalizado.

A tela de resolvedores personalizados na UI do App Services
2

Especifique o nome do App Services para o resolvedor na entrada GraphQL Field Name. O App Services expõe o resolvedor personalizado em seu tipo principal usando esse nome, portanto, o nome deve descrever o que o resolvedor faz de uma forma que seja útil para desenvolvedores que trabalham com GraphQL API.

3

O App Services expõem cada resolvedor personalizado como um campo em um tipo principal. O tipo principal pode ser uma query em nível raiz, uma mutação ou um tipo de documento gerado.

No menu suspenso Parent Type, selecione uma das seguintes opções:

Opção
Descrição
Query

O resolvedor é uma operação de nível de raiz query:

Exemplo

Um resolvedor personalizado para uma query denominada myCustomQuery tem o seguinte esquema gerado:

type Query {
myCustomQuery: DefaultPayload
...
}
Mutation

O resolvedor é uma operação de nível raiz mutation:

Exemplo

Um resolvedor personalizado para uma mutação denominada myCustomMutation tem o seguinte esquema gerado:

type Mutation {
myCustomMutation: DefaultPayload
...
}
Document Type

O resolvedor é uma propriedade computada no tipo de documento especificado. Qualquer query ou mutação que retorna o tipo de documento também pode solicitar propriedades calculadas definidas por resolvedores personalizados no tipo.

Exemplo

Um resolvedor personalizado que define uma propriedade computada no tipo Task denominado myCustomTaskProperty tem o seguinte esquema gerado:

type Task {
myCustomTaskProperty: DefaultPayload
...
}
4

Um resolvedor personalizado pode aceitar parâmetros de entrada da query ou mutação recebida. Você pode usar um tipo de entrada gerado existente ou definir um novo tipo de entrada personalizado especificamente para o resolvedor.

Se você especificar um tipo de entrada, o App Services expõe o parâmetro input na definição do esquema GraphQL gerado pelo resolvedor personalizado como um parâmetro opcional que aceita o tipo de entrada especificado. Se você não especificar um tipo de entrada, o resolvedor personalizado não aceitará nenhum argumento.

No menu suspenso Input Type, selecione uma das seguintes opções:

Opção
Descrição
None

O resolvedor não aceita nenhuma entrada.

Exemplo

Um resolvedor personalizado denominado myCustomQuery que não aceita uma entrada tem o seguinte esquema gerado:

type Query {
myCustomQuery: DefaultPayload
...
}
Scalar

O resolvedor usa um tipo escalar existente do esquema GraphQL gerado.

Na segunda entrada suspensa, selecione um único escalar ou uma array de múltiplos escalares do mesmo tipo.

Exemplo

Um resolvedor personalizado denominado myCustomQuery que utiliza a opção Scalar Type para especificar um tipo de entrada de DateTiem tem o seguinte esquema gerado:

type Query {
myCustomQuery(input: DateTime): DefaultPayload
...
}
Existing Type

O resolvedor usa um tipo de entrada existente do esquema GraphQL gerado.

Na segunda entrada suspensa, selecione um único objeto de entrada ou uma array de vários objetos de entrada do mesmo tipo.

Exemplo

Um resolvedor personalizado denominado myCustomQuery que utiliza a opção Existing Type para especificar um tipo de entrada de TaskInsertInput tem o seguinte esquema gerado:

type Query {
myCustomQuery(input: TaskInsertInput): DefaultPayload
...
}
Custom Type

O App Services gera um novo tipo de entrada especificamente para o resolvedor com base em um esquema definido por você. O esquema deve ser um object que contém pelo menos uma propriedade e um campo title que define um nome único para o tipo de entrada gerado.

Uma configuração de resolução personalizada para um tipo de entrada personalizado.

Exemplo

Um resolvedor personalizado denominado myCustomQuery que utiliza a opção Custom Type com um tipo de entrada denominado MyCustomQueryInput tem o seguinte esquema gerado:

input MyCustomQueryInput {
someArgument: String;
}
type Query {
myCustomQuery(input: MyCustomQueryInput): DefaultPayload
...
}
5

Todos os resolvedores GraphQL devem retornar uma carga útil que esteja em conformidade com um tipo específico no esquema. Para um resolvedor personalizado, você pode usar um tipo de documento gerado existente, definir um novo tipo de carga útil personalizada especificamente para o resolvedor ou usar uma carga útil padrão. O App Services inclui o tipo de carga útil especificado na definição do esquema GraphQL gerada pelo resolvedor personalizado.

No menu suspenso Payload Type, selecione uma das seguintes opções:

Opção
Descrição
DefaultPayload

O resolvedor retorna o tipo de DefaultPayload gerado automaticamente que tem a seguinte assinatura:

type DefaultPayload {
status: String!
}

O campo status sempre será resolvido como "complete", independente do valor de retorno da função de resolução.

{
status: "complete"
}

Exemplo

Um resolvedor personalizado denominado myCustomQuery que utiliza a opção DefaultPayload tem o seguinte esquema gerado:

type Query {
myCustomQuery: DefaultPayload
...
}
Scalar

O resolvedor usa um tipo escalar existente do esquema GraphQL gerado.

Na segunda entrada suspensa, selecione um único escalar ou uma array de múltiplos escalares do mesmo tipo.

Exemplo

Um resolvedor personalizado denominado myCustomQuery que usa a opção Scalar Type para especificar um tipo de carga útil do DateTime tem o seguinte esquema gerado:

type Query {
myCustomQuery: DateTime
...
}
Existing Type

O resolvedor retorna um tipo de documento existente do esquema GraphQL gerado.

Na segunda entrada suspensa, selecione um único tipo de documento ou uma array de vários documentos do mesmo tipo.

Exemplo

Um resolvedor personalizado denominado myCustomQuery que utiliza a opção Existing Type para especificar um tipo de entrada de TaskInsertInput tem o seguinte esquema gerado:

Um resolvedor personalizado denominado myCustomQuery que usa a opção Existing Type para especificar um tipo de carga útil do [Task] tem o seguinte esquema gerado:

type Query {
myCustomQuery: [Task]
...
}
Custom Type

O App Services gera um novo tipo de carga útil especificamente para o resolvedor com base em um esquema definido por você. O esquema deve ser um object que contém pelo menos uma propriedade e um campo title que define um nome único para o tipo de entrada gerado.

Uma configuração de resolução personalizada que define um novo tipo de carga útil personalizado.

Exemplo

Um resolvedor personalizado denominado myCustomQuery que usa a opção Custom Type com um tipo de carga útil denominado MyCustomQueryPayload tem o seguinte esquema gerado:

input MyCustomQueryPayload {
someValue: String;
}
type Query {
myCustomQuery: MyCustomQueryPayload
...
}
6

Quando um usuário chama um resolvedor personalizado, o App Services executa a função do resolvedor e retorna o resultado, que deve estar em conformidade com o Payload Type do resolvedor.

O App Services transmite à função todos os dados de entrada da operação, se aplicável. Se o resolvedor for uma propriedade calculada em um tipo de documento, o App Services transmitirá à função o documento específico em que o resolvedor foi chamado.

Uma função de resolução personalizada tem uma de duas assinaturas possíveis, dependendo se ela aceita ou não uma entrada:

Para definir a função do resolvedor, clique no menu suspenso Function e selecione uma função existente, ou crie uma nova.

7

Após configurar o resolvedor, clique em Save e distribua seu aplicativo. Depois de distribuído, você pode chamar o resolvedor personalizado por meio do GraphQL API.

Considere um dashboard hipotético que uma equipe de vendas usa para mostrar diversas estatísticas e outras métricas de desempenho em um determinado período de tempo. O dashboard usa os resolvedores personalizados nesta seção para gerenciar alguns de seus casos de uso específicos.

Todos os resolvedores podem acessar documentos Sale, que possuem o seguinte esquema:

O painel hipotético da equipe de vendas usa um resolvedor de queries personalizado que retorna dados agregados de vendas para um mês específico.

O App Services gera definições de esquema para os tipos de entrada e carga útil personalizados do resolvedor e adicionam o resolvedor ao seu tipo principal, o Query de nível raiz:

type Query {
averageSaleForMonth(input: AverageSaleForMonthInput): AverageSaleForMonthPayload
}
input AverageSalesForMonthInput {
month: String!;
year: String!;
}
type AverageSaleForMonthPayload {
month: String!;
year: String!;
averageSale: Float!;
}

O resolvedor usa a seguinte configuração:

Opção
Descrição
Parent Type
Query
GraphQL Field Name
averageSaleForMonth
Input Type

Tipo personalizado: AverageSaleForMonthInput

Payload Type

Tipo personalizado: AverageSaleForMonthPayload

Function
exports = async function averageSaleForMonth({ month, year }) {
const cluster = context.services.get("mongodb-atlas");
const sales = cluster.db("corp").collection("sales");
const averageSalePayload = await sales
.aggregate([
{ $match: { month: month, year: year } },
{
$group: {
_id: { month: "$month", year: "$year" },
averageSale: { $avg: "$saleTotal" },
}
},
{
$project: {
month: "$_id.month",
year: "$_id.year",
averageSale: 1
}
}
])
.next();
return averageSalePayload;
};

Para chamar esta query personalizada, você pode usar a seguinte operação e variáveis:

query GetAverageSaleForMonth($averageSaleInput: AverageSaleForMonthInput!) {
averageSaleForMonth(input: $averageSaleInput) {
month
year
averageSale
}
}
{
"variables": {
"averageSaleInput": { month: "March", year: "2020" }
}
}

O dashboard hipotético da equipe de vendas usa um resolvedor de mutação personalizado que adiciona uma nota de string a um documento Sale específico, identificado por seu _id.

O App Services gera definições de esquema para o tipo de entrada personalizado do resolvedor e adiciona o resolvedor ao seu tipo principal, o Mutation de nível raiz:

type Mutation {
addNoteToSale(input: AddNoteToSaleInput): Sale
}
input AddNoteToSaleInput {
sale_id: ObjectId!;
note: String!;
}

O resolvedor usa a seguinte configuração:

Opção
Descrição
Parent Type
Mutation
GraphQL Field Name
addNoteToSale
Input Type

Tipo personalizado: AddNoteToSaleInput

Payload Type

Tipo existente: Sale

Function
exports = async function addNoteToSale({ sale_id, note }) {
const cluster = context.services.get("mongodb-atlas");
const sales = cluster.db("corp").collection("sales");
const sale = await sales.findOneAndUpdate(
{ _id: sale_id },
{ $push: { notes: note } },
{ returnNewDocument: true }
);
return sale;
}

Para chamar esta query personalizada, você pode usar a seguinte operação e variáveis:

mutation AddNoteToSale($addNoteToSaleInput: AddNoteToSaleInput) {
addNoteToSale(input: $addNoteToSaleInput) {
_id
customer_id
month
year
saleTotal
notes
}
}
{
"variables": {
"addNoteToSaleInput": {
"sale_id": "5f3c2779796615b661fcdc25",
"note": "This was such a great sale!"
}
}
}

O dashboard hipotético da equipe de vendas usa um resolvedor personalizado que adiciona uma nova propriedade computada a cada documento Sale. Quando uma operação solicita o campo computado para um determinado Sale, o resolvedor faz query de um sistema externo e retorna os casos de suporte arquivados pelo cliente associado.

O App Services gera definições de esquema para o tipo de carga personalizada do resolvedor e adiciona o resolvedor ao seu tipo principal, Sale:

type Sale {
_id: ObjectId!
customer_id: String!
year: String!
month: String!
saleTotal: Float!
notes: [String]
customerSupportCases: [CustomerSupportCase]
}
type CustomerSupportCase {
caseId: String!
description: String!
}

O resolvedor usa a seguinte configuração:

Opção
Descrição
Parent Type
Sale
GraphQL Field Name
customerSupportCases
Input Type
none
Payload Type

Tipo personalizado: [CustomerSupportCase]

Function
exports = async function customerSupportCases(sale) {
// Return a list of objects from some external system
const cases = await fetchCustomerSupportCases({
customerId: sale.customer_id
});
return cases;
};

Para usar essa propriedade computada personalizada, você pode executar a seguinte operação:

query GetSalesWithSupportCases {
sales {
_id
customer_id
year
month
saleTotal
notes
customerSupportCases {
caseId
description
}
}
}
← Tipos, Resolvedores e Operadores do GraphQL