AWS AppSync JavaScript referência da função de resolução para Amazon RDS - AWS AppSync GraphQL

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á.

AWS AppSync JavaScript referência da função de resolução para Amazon RDS

A função e o resolvedor do AWS AppSync RDS permitem que os desenvolvedores enviem SQL consultas para um banco de dados de cluster do Amazon Aurora usando a API de dados do RDS e recuperem o resultado dessas consultas. Você pode escrever SQL instruções que são enviadas para a API de dados usando AWS AppSync o modelo sql com tag de rds módulo ou usando as funções remove auxiliaresselect, insertupdate, e do rds módulo. AWS AppSync utiliza a ExecuteStatementação do RDS Data Service para executar instruções SQL no banco de dados.

Modelo marcado com SQL

AWS AppSync O modelo sql marcado permite que você crie uma declaração estática que pode receber valores dinâmicos em tempo de execução usando expressões de modelo. AWS AppSync cria um mapa variável a partir dos valores da expressão para criar uma SqlParameterizedconsulta que é enviada para a API de dados sem servidor do Amazon Aurora. Com esse método, não é possível que valores dinâmicos transmitidos em runtime modifiquem a declaração original, o que pode causar uma execução não intencional. Todos os valores dinâmicos são transmitidos como parâmetros, não podem modificar a declaração original e não são executados pelo banco de dados. Isso torna a consulta menos vulnerável a ataques de injeção de SQL.

nota

Em todos os casos, ao redigir declarações SQL, é necessário seguir as diretrizes de segurança para lidar adequadamente com os dados recebidos como entrada.

nota

O modelo marcado com sql só aceita a transmissão de valores de variáveis. Não é possível usar uma expressão para especificar dinamicamente nomes de colunas ou de tabelas. No entanto, é possível usar funções de utilitário para criar declarações dinâmicas.

No exemplo a seguir, criamos uma consulta que filtra com base no valor do argumento col definido dinamicamente na consulta do GraphQL em runtime. O valor só pode ser adicionado à declaração usando a expressão de tag:

import { sql, createMySQLStatement } from '@aws-appsync/utils/rds'; export function request(ctx) { const query = sql` SELECT * FROM table WHERE column = ${ctx.args.col}` ; return createMySQLStatement(query); }

Ao transmitir todos os valores dinâmicos pelo mapa de variáveis, contamos com o mecanismo de banco de dados para processar e higienizar os valores com segurança.

Criar declarações

Funções e resolvedores podem interagir com bancos de dados MySQL e PostgreSQL. Use createMySQLStatement e createPgStatement, respectivamente, para criar declarações. Por exemplo, createMySQLStatement pode criar uma consulta MySQL. Essas funções aceitam até duas declarações, o que é útil quando uma solicitação deve recuperar os resultados imediatamente. Com MySQL, é possível fazer o seguinte:

import { sql, createMySQLStatement } from '@aws-appsync/utils/rds'; export function request(ctx) { const { id, text } = ctx.args; const s1 = sql`insert into Post(id, text) values(${id}, ${text})`; const s2 = sql`select * from Post where id = ${id}`; return createMySQLStatement(s1, s2); }
nota

createPgStatement e createMySQLStatement não inserem caracteres de escape nem citam declarações criadas com o modelo marcado com sql.

Recuperação de dados

O resultado da declaração SQL executada está disponível no manipulador de respostas, no objeto context.result. O resultado é uma string JSON com os elementos de resposta da ação ExecuteStatement. Quando analisado, o resultado tem o seguinte formato:

type SQLStatementResults = { sqlStatementResults: { records: any[]; columnMetadata: any[]; numberOfRecordsUpdated: number; generatedFields?: any[] }[] }

É possível usar o utilitário toJsonObject para transformar o resultado em uma lista de objetos JSON representando as linhas exibidas. Por exemplo:

import { toJsonObject } from '@aws-appsync/utils/rds'; export function response(ctx) { const { error, result } = ctx; if (error) { return util.appendError( error.message, error.type, result ) } return toJsonObject(result)[1][0] }

Observe que o toJsonObject exibe uma matriz de resultados das declarações. Se você forneceu uma declaração, o tamanho da matriz será 1. Se você forneceu duas declarações, o tamanho da matriz será 2. Cada resultado na matriz contém 0 ou mais linhas. toJsonObject exibirá null se o valor do resultado for inválido ou inesperado.

Funções do utilitário

Você pode usar os auxiliares utilitários do módulo AWS AppSync RDS para interagir com seu banco de dados.

O utilitário select cria uma declaração SELECT para consultar o banco de dados relacional.

Uso básico

Na forma básica, é possível especificar a tabela que deseja consultar:

import { select, createPgStatement } from '@aws-appsync/utils/rds'; export function request(ctx) { // Generates statement: // "SELECT * FROM "persons" return createPgStatement(select({table: 'persons'})); }

Observe também que é possível especificar o esquema no identificador da tabela:

import { select, createPgStatement } from '@aws-appsync/utils/rds'; export function request(ctx) { // Generates statement: // SELECT * FROM "private"."persons" return createPgStatement(select({table: 'private.persons'})); }

Especificar colunas

É possível especificar colunas com a propriedade columns. Se isso não for definido como um valor, o padrão será *:

export function request(ctx) { // Generates statement: // SELECT "id", "name" // FROM "persons" return createPgStatement(select({ table: 'persons', columns: ['id', 'name'] })); }

Também é possível especificar a tabela de uma coluna:

export function request(ctx) { // Generates statement: // SELECT "id", "persons"."name" // FROM "persons" return createPgStatement(select({ table: 'persons', columns: ['id', 'persons.name'] })); }

Limites e deslocamentos:

É possível aplicar limit e offset à consulta:

export function request(ctx) { // Generates statement: // SELECT "id", "name" // FROM "persons" // LIMIT :limit // OFFSET :offset return createPgStatement(select({ table: 'persons', columns: ['id', 'name'], limit: 10, offset: 40 })); }

Ordenar por

É possível classificar os resultados com a propriedade orderBy. Forneça uma matriz de objetos especificando a coluna e uma propriedade dir opcional:

export function request(ctx) { // Generates statement: // SELECT "id", "name" FROM "persons" // ORDER BY "name", "id" DESC return createPgStatement(select({ table: 'persons', columns: ['id', 'name'], orderBy: [{column: 'name'}, {column: 'id', dir: 'DESC'}] })); }

Filtros

É possível criar filtros usando o objeto de condição especial:

export function request(ctx) { // Generates statement: // SELECT "id", "name" // FROM "persons" // WHERE "name" = :NAME return createPgStatement(select({ table: 'persons', columns: ['id', 'name'], where: {name: {eq: 'Stephane'}} })); }

Também é possível combinar filtros:

export function request(ctx) { // Generates statement: // SELECT "id", "name" // FROM "persons" // WHERE "name" = :NAME and "id" > :ID return createPgStatement(select({ table: 'persons', columns: ['id', 'name'], where: {name: {eq: 'Stephane'}, id: {gt: 10}} })); }

Também é possível criar declarações OR:

export function request(ctx) { // Generates statement: // SELECT "id", "name" // FROM "persons" // WHERE "name" = :NAME OR "id" > :ID return createPgStatement(select({ table: 'persons', columns: ['id', 'name'], where: { or: [ { name: { eq: 'Stephane'} }, { id: { gt: 10 } } ]} })); }

Também é possível negar uma condição com not:

export function request(ctx) { // Generates statement: // SELECT "id", "name" // FROM "persons" // WHERE NOT ("name" = :NAME AND "id" > :ID) return createPgStatement(select({ table: 'persons', columns: ['id', 'name'], where: { not: [ { name: { eq: 'Stephane'} }, { id: { gt: 10 } } ]} })); }

Também é possível usar os seguintes operadores para comparar valores:

Operador Description Tipos de valores possíveis
eq Equal número, string, booleano
ne Not equal número, string, booleano
le Menor ou igual a número, string
lt Menor que número, string
idade Maior ou igual a número, string
gt Maior que número, string
contém Like string
NÃO contém Não é como string
Começa com Começa com o prefixo string
entre Entre dois valores número, string
O atributo existe O atributo não é nulo número, string, booleano
size verifica o comprimento do elemento string

O utilitário insert oferece uma maneira simples de inserir itens de linha única no banco de dados com a operação INSERT.

Inserções de item único

Para inserir um item, especifique a tabela e, depois, transmita o objeto de valores. As chaves do objeto são associadas às colunas da tabela. São inseridos automaticamente caracteres de escape nos nomes das colunas e os valores são enviados ao banco de dados usando o mapa de variáveis:

import { insert, createMySQLStatement } from '@aws-appsync/utils/rds'; export function request(ctx) { const { input: values } = ctx.args; const insertStatement = insert({ table: 'persons', values }); // Generates statement: // INSERT INTO `persons`(`name`) // VALUES(:NAME) return createMySQLStatement(insertStatement) }

Caso de uso do MySQL

É possível combinar um insert seguido por um select para recuperar a linha inserida:

import { insert, select, createMySQLStatement } from '@aws-appsync/utils/rds'; export function request(ctx) { const { input: values } = ctx.args; const insertStatement = insert({ table: 'persons', values }); const selectStatement = select({ table: 'persons', columns: '*', where: { id: { eq: values.id } }, limit: 1, }); // Generates statement: // INSERT INTO `persons`(`name`) // VALUES(:NAME) // and // SELECT * // FROM `persons` // WHERE `id` = :ID return createMySQLStatement(insertStatement, selectStatement) }

Caso de uso do Postgres

Com o Postgres, é possível usar returning para obter dados da linha que você inseriu. Ele aceita * ou uma matriz de nomes de colunas:

import { insert, createPgStatement } from '@aws-appsync/utils/rds'; export function request(ctx) { const { input: values } = ctx.args; const insertStatement = insert({ table: 'persons', values, returning: '*' }); // Generates statement: // INSERT INTO "persons"("name") // VALUES(:NAME) // RETURNING * return createPgStatement(insertStatement) }

O utilitário update permite atualizar as linhas existentes. É possível usar o objeto de condição para aplicar alterações às colunas especificadas em todas as linhas que atendam à condição. Por exemplo, digamos que temos um esquema que nos permita fazer essa mutação. Queremos atualizar o name de Person com o valor id de 3, mas somente se os conhecermos (known_since) desde o ano 2000:

mutation Update { updatePerson( input: {id: 3, name: "Jon"}, condition: {known_since: {ge: "2000"}} ) { id name } }

Nosso resolvedor de atualização é semelhante a:

import { update, createPgStatement } from '@aws-appsync/utils/rds'; export function request(ctx) { const { input: { id, ...values }, condition } = ctx.args; const where = { ...condition, id: { eq: id }, }; const updateStatement = update({ table: 'persons', values, where, returning: ['id', 'name'], }); // Generates statement: // UPDATE "persons" // SET "name" = :NAME, "birthday" = :BDAY, "country" = :COUNTRY // WHERE "id" = :ID // RETURNING "id", "name" return createPgStatement(updateStatement) }

Podemos adicionar uma verificação à nossa condição para garantir que somente a linha que tem a chave primária id igual a 3 seja atualizada. Da mesma forma, para Postgres inserts, é possível usar returning para exibir os dados modificados.

O utilitário remove permite excluir as linhas existentes. É possível usar o objeto de condição em todas as linhas que atendam à condição. Observe que delete é uma palavra-chave reservada em JavaScript. removedeve ser usado em vez disso:

import { remove, createPgStatement } from '@aws-appsync/utils/rds'; export function request(ctx) { const { input: { id }, condition } = ctx.args; const where = { ...condition, id: { eq: id } }; const deleteStatement = remove({ table: 'persons', where, returning: ['id', 'name'], }); // Generates statement: // DELETE "persons" // WHERE "id" = :ID // RETURNING "id", "name" return createPgStatement(updateStatement) }

Conversão

Em alguns casos, convém ter maior especificidade sobre o tipo de objeto correto a ser usado na declaração. Você pode usar as dicas de tipo fornecidas para especificar o tipo dos seus parâmetros. AWS AppSync suporta os mesmos tipos de dicas da API de dados. Você pode converter seus parâmetros usando as typeHint funções do AWS AppSync rds módulo.

O exemplo a seguir permite enviar uma matriz como um valor que é convertido como um objeto JSON. Usamos o operador -> para recuperar o elemento index 2 na matriz JSON:

import { sql, createPgStatement, toJsonObject, typeHint } from '@aws-appsync/utils/rds'; export function request(ctx) { const arr = ctx.args.list_of_ids const statement = sql`select ${typeHint.JSON(arr)}->2 as value` return createPgStatement(statement) } export function response(ctx) { return toJsonObject(ctx.result)[0][0].value }

A conversão também é útil ao processar e comparar DATE, TIME e TIMESTAMP:

import { select, createPgStatement, typeHint } from '@aws-appsync/utils/rds'; export function request(ctx) { const when = ctx.args.when const statement = select({ table: 'persons', where: { createdAt : { gt: typeHint.DATETIME(when) } } }) return createPgStatement(statement) }

Veja outro exemplo de como enviar a data e a hora atuais:

import { sql, createPgStatement, typeHint } from '@aws-appsync/utils/rds'; export function request(ctx) { const now = util.time.nowFormatted('YYYY-MM-dd HH:mm:ss') return createPgStatement(sql`select ${typeHint.TIMESTAMP(now)}`) }

Dicas de tipo disponíveis

  • typeHint.DATE: o parâmetro correspondente é enviado como objeto do tipo DATE ao banco de dados. O formato aceito é YYYY-MM-DD.

  • typeHint.DECIMAL: o parâmetro correspondente é enviado como objeto do tipo DECIMAL ao banco de dados.

  • typeHint.JSON: o parâmetro correspondente é enviado como objeto do tipo JSON ao banco de dados.

  • typeHint.TIME: o valor de parâmetro de string correspondente é enviado como objeto do tipo TIME ao banco de dados. O formato aceito é HH:MM:SS[.FFF].

  • typeHint.TIMESTAMP: o valor de parâmetro de string correspondente é enviado como objeto do tipo TIMESTAMP ao banco de dados. O formato aceito é YYYY-MM-DD HH:MM:SS[.FFF].

  • typeHint.UUID: o valor de parâmetro de string correspondente é enviado como objeto do tipo UUID ao banco de dados.