Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Utilisation d'Aurora Postgre SQL avec des données API dans AWS AppSync
AWS AppSync fournit une source de données pour exécuter SQL des instructions sur des clusters Amazon Aurora activés avec une donnéeAPI. Vous pouvez utiliser des AWS AppSync résolveurs pour exécuter SQL des instructions sur les données à l'APIaide de requêtes GraphQL, de mutations et d'abonnements.
Note
Ce didacticiel utilise la région US-EAST-1
.
Création de clusters
Avant d'ajouter une source de RDS données Amazon AWS AppSync, activez d'abord une donnée API sur un cluster Aurora Serverless. Vous devez également configurer un secret à l'aide de AWS Secrets Manager. Pour créer un cluster Aurora Serverless, vous pouvez utiliser : AWS CLI
aws rds create-db-cluster \ --db-cluster-identifier appsync-tutorial \ --engine aurora-postgresql --engine-version 13.11 \ --engine-mode serverless \ --master-username USERNAME \ --master-user-password COMPLEX_PASSWORD
Cela renverra un ARN pour le cluster. Vous pouvez vérifier l'état de votre cluster à l'aide de la commande suivante :
aws rds describe-db-clusters \ --db-cluster-identifier appsync-tutorial \ --query "DBClusters[0].Status"
Créez un secret via la AWS Secrets Manager console ou AWS CLI avec un fichier d'entrée tel que le suivant en utilisant le USERNAME
et COMPLEX_PASSWORD
de l'étape précédente :
{ "username": "USERNAME", "password": "COMPLEX_PASSWORD" }
Passez ceci en tant que paramètre à CLI :
aws secretsmanager create-secret \ --name appsync-tutorial-rds-secret \ --secret-string file://creds.json
Cela renverra et ARN révélera le secret. Prenez note ARN de votre cluster Aurora Serverless et de Secret pour plus tard lors de la création d'une source de données dans la AWS AppSync console.
Données habilitantes API
Une fois que le statut de votre cluster est passé àavailable
, activez les données API en suivant la RDSdocumentation Amazon. Les données API doivent être activées avant de les ajouter en tant que source de AWS AppSync données. Vous pouvez également activer les données API à l'aide de AWS CLI :
aws rds modify-db-cluster \ --db-cluster-identifier appsync-tutorial \ --enable-http-endpoint \ --apply-immediately
Création de la base de données et de la table
Après avoir activé vos donnéesAPI, validez qu'elles fonctionnent à l'aide de la aws rds-data
execute-statement
commande du AWS CLI. Cela garantit que votre cluster Aurora Serverless est correctement configuré avant de l'ajouter au AWS AppSync API. Créez d'abord une TESTDBbase de données avec le --sql
paramètre :
aws rds-data execute-statement \ --resource-arn "arn:aws:rds:us-east-1:123456789012:cluster:appsync-tutorial" \ --secret-arn "arn:aws:secretsmanager:us-east-1:123456789012:secret:appsync-tutorial-rds-secret" \ --sql "create DATABASE \"testdb\""
Si cela fonctionne sans erreur, ajoutez deux tables avec la create table
commande :
aws rds-data execute-statement \ --resource-arn "arn:aws:rds:us-east-1:123456789012:cluster:appsync-tutorial" \ --secret-arn "arn:aws:secretsmanager:us-east-1:123456789012:secret:appsync-tutorial-rds-secret" \ --database "testdb" \ --sql 'create table public.todos (id serial constraint todos_pk primary key, description text not null, due date not null, "createdAt" timestamp default now());' aws rds-data execute-statement \ --resource-arn "arn:aws:rds:us-east-1:123456789012:cluster:appsync-tutorial" \ --secret-arn "arn:aws:secretsmanager:us-east-1:123456789012:secret:appsync-tutorial-rds-secret" \ --database "testdb" \ --sql 'create table public.tasks (id serial constraint tasks_pk primary key, description varchar, "todoId" integer not null constraint tasks_todos_id_fk references public.todos);'
Si tout fonctionne sans problème, vous pouvez désormais ajouter le cluster en tant que source de données dans votreAPI.
Création d'un schéma GraphQL
Maintenant que vos données Aurora Serverless API s'exécutent avec des tables configurées, nous allons créer un schéma GraphQL. Vous pouvez le faire manuellement, mais cela vous AWS AppSync permet de démarrer rapidement en important la configuration des tables depuis une base de données existante à l'aide de l'assistant de API création.
Pour commencer :
-
Dans la AWS AppSync console, choisissez Create API, puis Start with a Amazon Aurora cluster.
-
Spécifiez des API détails tels que le APInom, puis sélectionnez votre base de données pour générer leAPI.
-
Choisissez votre base de données. Si nécessaire, mettez à jour la région, puis choisissez votre cluster Aurora et votre TESTDBbase de données.
-
Choisissez votre secret, puis choisissez Importer.
-
Une fois les tables découvertes, mettez à jour les noms des types. Changez
Todos
versTodo
etTasks
versTask
. -
Prévisualisez le schéma généré en choisissant Aperçu du schéma. Votre schéma ressemblera à ceci :
type Todo { id: Int! description: String! due: AWSDate! createdAt: String } type Task { id: Int! todoId: Int! description: String }
-
Pour le rôle, vous pouvez soit AWS AppSync créer un nouveau rôle, soit en créer un avec une politique similaire à celle ci-dessous :
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "rds-data:ExecuteStatement", ], "Resource": [ "arn:aws:rds:us-east-1:123456789012:cluster:appsync-tutorial", "arn:aws:rds:us-east-1:123456789012:cluster:appsync-tutorial:*" ] }, { "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue" ], "Resource": [ "arn:aws:secretsmanager:us-east-1:123456789012:secret:your:secret:arn:appsync-tutorial-rds-secret", "arn:aws:secretsmanager:us-east-1:123456789012:secret:your:secret:arn:appsync-tutorial-rds-secret:*" ] } ] }
Notez que cette politique contient deux déclarations auxquelles vous accordez un accès aux rôles. La première ressource est votre cluster Aurora et la seconde est votre AWS Secrets Manager ARN.
Choisissez Suivant, passez en revue les détails de configuration, puis choisissez Créer API. Vous disposez désormais d'un système totalement opérationnelAPI. Vous pouvez consulter tous les détails de votre schéma API sur la page Schéma.
Résolveurs pour RDS
Le flux de API création a automatiquement créé les résolveurs pour interagir avec nos types. Si vous regardez la page Schéma, vous trouverez les résolveurs nécessaires pour :
-
Créez un
todo
via leMutation.createTodo
champ. -
Mettez à jour un
todo
via leMutation.updateTodo
champ. -
Supprimez un
todo
via leMutation.deleteTodo
champ. -
Obtenez-en un
todo
sur leQuery.getTodo
terrain. -
todos
Répertoriez tout via leQuery.listTodos
champ.
Vous trouverez des champs et des résolveurs similaires attachés au Task
type. Examinons de plus près certains des résolveurs.
Mutation. createTodo
Dans l'éditeur de schéma de la AWS AppSync console, sur le côté droit, choisissez à testdb
côté decreateTodo(...): Todo
. Le code du résolveur utilise la insert
fonction du rds
module pour créer dynamiquement une instruction d'insertion qui ajoute des données à la todos
table. Comme nous travaillons avec Postgres, nous pouvons tirer parti de returning
cette instruction pour récupérer les données insérées.
Mettons à jour le résolveur pour spécifier correctement le DATE
type du due
champ :
import { util } from '@aws-appsync/utils'; import { insert, createPgStatement, toJsonObject, typeHint } from '@aws-appsync/utils/rds'; export function request(ctx) { const { input } = ctx.args; // if a due date is provided, cast is as `DATE` if (input.due) { input.due = typeHint.DATE(input.due) } const insertStatement = insert({ table: 'todos', values: input, returning: '*', }); return createPgStatement(insertStatement) } export function response(ctx) { const { error, result } = ctx; if (error) { return util.appendError( error.message, error.type, result ) } return toJsonObject(result)[0][0] }
Enregistrez le résolveur. L'indice de type marque le type due
correct dans notre objet d'entrée en tant que DATE
type. Cela permet au moteur Postgres d'interpréter correctement la valeur. Ensuite, mettez à jour votre schéma pour le supprimer id
de l'CreateTodo
entrée. Comme notre base de données Postgres peut renvoyer l'identifiant généré, nous pouvons nous y fier pour la création et le renvoi du résultat sous la forme d'une seule requête :
input CreateTodoInput { due: AWSDate! createdAt: String description: String! }
Apportez la modification et mettez à jour votre schéma. Accédez à l'éditeur de requêtes pour ajouter un élément à la base de données :
mutation CreateTodo { createTodo(input: {description: "Hello World!", due: "2023-12-31"}) { id due description createdAt } }
Vous obtenez le résultat :
{ "data": { "createTodo": { "id": 1, "due": "2023-12-31", "description": "Hello World!", "createdAt": "2023-11-14 20:47:11.875428" } } }
Requête. listTodos
Dans l'éditeur de schéma de la console, sur le côté droit, choisissez à testdb
côté delistTodos(id: ID!): Todo
. Le gestionnaire de demandes utilise la fonction utilitaire de sélection pour créer une demande de manière dynamique au moment de l'exécution.
export function request(ctx) { const { filter = {}, limit = 100, nextToken } = ctx.args; const offset = nextToken ? +util.base64Decode(nextToken) : 0; const statement = select({ table: 'todos', columns: '*', limit, offset, where: filter, }); return createPgStatement(statement) }
Nous voulons filtrer todos
en fonction de la due
date. Mettons à jour le résolveur vers lequel convertir due
DATE
les valeurs. Mettez à jour la liste des importations et le gestionnaire de demandes :
import { util } from '@aws-appsync/utils'; import * as rds from '@aws-appsync/utils/rds'; export function request(ctx) { const { filter: where = {}, limit = 100, nextToken } = ctx.args; const offset = nextToken ? +util.base64Decode(nextToken) : 0; // if `due` is used in a filter, CAST the values to DATE. if (where.due) { Object.entries(where.due).forEach(([k, v]) => { if (k === 'between') { where.due[k] = v.map((d) => rds.typeHint.DATE(d)); } else { where.due[k] = rds.typeHint.DATE(v); } }); } const statement = rds.select({ table: 'todos', columns: '*', limit, offset, where, }); return rds.createPgStatement(statement); } export function response(ctx) { const { args: { limit = 100, nextToken }, error, result, } = ctx; if (error) { return util.appendError(error.message, error.type, result); } const offset = nextToken ? +util.base64Decode(nextToken) : 0; const items = rds.toJsonObject(result)[0]; const endOfResults = items?.length < limit; const token = endOfResults ? null : util.base64Encode(`${offset + limit}`); return { items, nextToken: token }; }
Essayons la requête. Dans l'éditeur de requêtes :
query LIST { listTodos(limit: 10, filter: {due: {between: ["2021-01-01", "2025-01-02"]}}) { items { id due description } } }
Mutation. updateTodo
Vous pouvez également update
unTodo
. Dans l'éditeur de requêtes, mettons à jour notre premier Todo
élément de id
1
.
mutation UPDATE { updateTodo(input: {id: 1, description: "edits"}) { description due id } }
Notez que vous devez spécifier id
l'élément que vous mettez à jour. Vous pouvez également spécifier une condition pour ne mettre à jour qu'un élément répondant à des conditions spécifiques. Par exemple, il se peut que nous souhaitions modifier l'article uniquement si la description commence par edits
:
mutation UPDATE { updateTodo(input: {id: 1, description: "edits: make a change"}, condition: {description: {beginsWith: "edits"}}) { description due id } }
Tout comme nous avons géré nos create
list
opérations, nous pouvons mettre à jour notre résolveur pour transformer le due
champ en unDATE
. Enregistrez ces modifications dans updateTodo
:
import { util } from '@aws-appsync/utils'; import * as rds from '@aws-appsync/utils/rds'; export function request(ctx) { const { input: { id, ...values }, condition = {}, } = ctx.args; const where = { ...condition, id: { eq: id } }; // if `due` is used in a condition, CAST the values to DATE. if (condition.due) { Object.entries(condition.due).forEach(([k, v]) => { if (k === 'between') { condition.due[k] = v.map((d) => rds.typeHint.DATE(d)); } else { condition.due[k] = rds.typeHint.DATE(v); } }); } // if a due date is provided, cast is as `DATE` if (values.due) { values.due = rds.typeHint.DATE(values.due); } const updateStatement = rds.update({ table: 'todos', values, where, returning: '*', }); return rds.createPgStatement(updateStatement); } export function response(ctx) { const { error, result } = ctx; if (error) { return util.appendError(error.message, error.type, result); } return rds.toJsonObject(result)[0][0]; }
Maintenant, essayez une mise à jour avec une condition :
mutation UPDATE { updateTodo( input: { id: 1, description: "edits: make a change", due: "2023-12-12"}, condition: { description: {beginsWith: "edits"}, due: {ge: "2023-11-08"}}) { description due id } }
Mutation. deleteTodo
Vous pouvez delete
Todo
utiliser la deleteTodo
mutation. Cela fonctionne comme la updateTodo
mutation, et vous devez spécifier id
l'élément que vous souhaitez supprimer :
mutation DELETE { deleteTodo(input: {id: 1}) { description due id } }
Rédaction de requêtes personnalisées
Nous avons utilisé les utilitaires du rds
module pour créer nos SQL instructions. Nous pouvons également écrire notre propre déclaration statique personnalisée pour interagir avec notre base de données. Commencez par mettre à jour le schéma pour supprimer le id
champ de l'CreateTask
entrée.
input CreateTaskInput { todoId: Int! description: String }
Créez ensuite quelques tâches. Une tâche possède une relation de clé étrangère avec Todo
:
mutation TASKS { a: createTask(input: {todoId: 2, description: "my first sub task"}) { id } b:createTask(input: {todoId: 2, description: "another sub task"}) { id } c: createTask(input: {todoId: 2, description: "a final sub task"}) { id } }
Créez un nouveau champ de votre Query
type appelé getTodoAndTasks
:
getTodoAndTasks(id: Int!): Todo
Ajoutez un tasks
champ au Todo
type :
type Todo { due: AWSDate! id: Int! createdAt: String description: String! tasks:TaskConnection }
Enregistrez le schéma. Dans l'éditeur de schéma de la console, sur le côté droit, choisissez Attach Resolver forgetTodosAndTasks(id:
Int!): Todo
. Choisissez votre source RDS de données Amazon. Mettez à jour votre résolveur avec le code suivant :
import { sql, createPgStatement,toJsonObject } from '@aws-appsync/utils/rds'; export function request(ctx) { return createPgStatement( sql`SELECT * from todos where id = ${ctx.args.id}`, sql`SELECT * from tasks where "todoId" = ${ctx.args.id}`); } export function response(ctx) { const result = toJsonObject(ctx.result); const todo = result[0][0]; if (!todo) { return null; } todo.tasks = { items: result[1] }; return todo; }
Dans ce code, nous utilisons le modèle de sql
balise pour écrire une SQL instruction à laquelle nous pouvons transmettre une valeur dynamique en toute sécurité lors de l'exécution. createPgStatement
peut traiter jusqu'à deux SQL demandes à la fois. Nous l'utilisons pour envoyer une requête pour notre todo
et une autre pour notretasks
. Vous auriez pu le faire avec une JOIN
déclaration ou toute autre méthode d'ailleurs. L'idée est de pouvoir rédiger votre propre SQL déclaration pour mettre en œuvre votre logique métier. Pour utiliser la requête dans l'éditeur de requêtes, nous pouvons essayer ceci :
query TodoAndTasks { getTodosAndTasks(id: 2) { id due description tasks { items { id description } } } }
Supprimer votre cluster
Important
La suppression d'un cluster est définitive. Passez en revue votre projet de manière approfondie avant de réaliser cette action.
Pour supprimer votre cluster :
$ aws rds delete-db-cluster \ --db-cluster-identifier appsync-tutorial \ --skip-final-snapshot