Menggunakan Aurora SQL Postgre dengan Data di API AWS AppSync - AWS AppSync

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Menggunakan Aurora SQL Postgre dengan Data di API AWS AppSync

AWS AppSync menyediakan sumber data untuk mengeksekusi SQL pernyataan terhadap klaster Amazon Aurora yang diaktifkan dengan Data. API Anda dapat menggunakan AWS AppSync resolver untuk menjalankan SQL pernyataan terhadap data dengan kueri, mutasi, dan API langganan GraphQL.

catatan

Tutorial ini menggunakan Wilayah US-EAST-1.

Membuat cluster

Sebelum menambahkan sumber RDS data Amazon ke AWS AppSync, pertama-tama aktifkan Data API pada klaster Tanpa Server Aurora. Anda juga harus mengkonfigurasi rahasia menggunakan AWS Secrets Manager. Untuk membuat cluster Aurora Tanpa Server, Anda dapat menggunakan: 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

Ini akan mengembalikan ARN untuk cluster. Anda dapat memeriksa status cluster Anda dengan perintah:

aws rds describe-db-clusters \ --db-cluster-identifier appsync-tutorial \ --query "DBClusters[0].Status"

Buat Rahasia melalui AWS Secrets Manager Konsol atau AWS CLI dengan file input seperti berikut menggunakan USERNAME dan COMPLEX_PASSWORD dari langkah sebelumnya:

{ "username": "USERNAME", "password": "COMPLEX_PASSWORD" }

Berikan ini sebagai parameter keCLI:

aws secretsmanager create-secret \ --name appsync-tutorial-rds-secret \ --secret-string file://creds.json

Ini akan mengembalikan rahasia. ARN Catat klaster Aurora Tanpa Server dan Rahasia Anda untuk nanti saat membuat sumber data di konsol. ARN AWS AppSync

Mengaktifkan data API

Setelah status klaster Anda berubahavailable, aktifkan Data API dengan mengikuti RDSdokumentasi Amazon. Data API harus diaktifkan sebelum menambahkannya sebagai sumber AWS AppSync data. Anda juga dapat mengaktifkan Data API menggunakan AWS CLI:

aws rds modify-db-cluster \ --db-cluster-identifier appsync-tutorial \ --enable-http-endpoint \ --apply-immediately

Membuat database dan tabel

Setelah mengaktifkan Data AndaAPI, validasi itu berfungsi menggunakan aws rds-data execute-statement perintah di file. AWS CLI Ini memastikan bahwa cluster Aurora Serverless Anda dikonfigurasi dengan benar sebelum menambahkannya ke. AWS AppSync API Pertama, buat TESTDBdatabase dengan --sql parameter:

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\""

Jika ini berjalan tanpa kesalahan, tambahkan dua tabel dengan create table perintah:

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);'

Jika semuanya berjalan tanpa masalah, Anda sekarang dapat menambahkan cluster sebagai sumber data di file AndaAPI.

Membuat skema GraphQL

Sekarang setelah Data API Tanpa Server Aurora Anda berjalan dengan tabel yang dikonfigurasi, kami akan membuat skema GraphQL. Anda dapat melakukannya secara manual, tetapi AWS AppSync memungkinkan Anda memulai dengan cepat dengan mengimpor konfigurasi tabel dari database yang ada menggunakan wizard API pembuatan.

Untuk memulai:

  1. Di AWS AppSync konsol, pilih Buat API, lalu Mulai dengan cluster Amazon Aurora.

  2. Tentukan API detail seperti APInama, lalu pilih database Anda untuk menghasilkanAPI.

  3. Pilih database Anda. Jika perlu, perbarui Wilayah, lalu pilih cluster dan TESTDBdatabase Aurora Anda.

  4. Pilih Rahasia Anda, lalu pilih Impor.

  5. Setelah tabel ditemukan, perbarui nama jenisnya. Ubah Todos ke Todo dan Tasks keTask.

  6. Pratinjau skema yang dihasilkan dengan memilih Skema Pratinjau. Skema Anda akan terlihat seperti ini:

    type Todo { id: Int! description: String! due: AWSDate! createdAt: String } type Task { id: Int! todoId: Int! description: String }
  7. Untuk peran tersebut, Anda dapat AWS AppSync membuat peran baru atau membuat peran dengan kebijakan yang mirip dengan yang di bawah ini:

    { "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:*" ] } ] }

    Perhatikan bahwa ada dua pernyataan dalam kebijakan ini yang Anda berikan akses peran. Sumber daya pertama adalah cluster Aurora Anda dan yang kedua adalah milik Anda. AWS Secrets Manager ARN

    Pilih Berikutnya, tinjau detail konfigurasi, lalu pilih Buat API. Anda sekarang memiliki operasional penuhAPI. Anda dapat meninjau detail lengkap Anda API di halaman Skema.

Resolver untuk RDS

Alur API pembuatan secara otomatis membuat resolver untuk berinteraksi dengan tipe kami. Jika Anda melihat halaman Skema, Anda akan menemukan resolver yang diperlukan untuk:

  • Buat todo melalui Mutation.createTodo bidang.

  • Perbarui todo melalui Mutation.updateTodo bidang.

  • Hapus todo melalui Mutation.deleteTodo bidang.

  • Dapatkan satu todo melalui Query.getTodo lapangan.

  • Daftar semua todos melalui Query.listTodos bidang.

Anda akan menemukan bidang dan resolver serupa yang dilampirkan untuk jenisnya. Task Mari kita lihat lebih dekat beberapa resolver.

Mutasi. createTodo

Dari editor skema di AWS AppSync konsol, di sisi kanan, pilih di testdb sebelahcreateTodo(...): Todo. Kode resolver menggunakan insert fungsi dari rds modul untuk secara dinamis membuat pernyataan insert yang menambahkan data ke tabel. todos Karena kami bekerja dengan Postgres, kami dapat memanfaatkan returning pernyataan untuk mendapatkan data yang dimasukkan kembali.

Mari kita perbarui resolver untuk menentukan DATE jenis bidang dengan benar: due

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] }

Simpan resolver. Petunjuk tipe menandai due dengan benar di objek input kami sebagai DATE tipe. Hal ini memungkinkan mesin Postgres untuk menafsirkan nilai dengan benar. Selanjutnya, perbarui skema Anda untuk menghapus id dari CreateTodo input. Karena database Postgres kami dapat mengembalikan ID yang dihasilkan, kami dapat mengandalkannya untuk pembuatan dan mengembalikan hasilnya sebagai satu permintaan:

input CreateTodoInput { due: AWSDate! createdAt: String description: String! }

Buat perubahan dan perbarui skema Anda. Buka editor Kueri untuk menambahkan item ke database:

mutation CreateTodo { createTodo(input: {description: "Hello World!", due: "2023-12-31"}) { id due description createdAt } }

Anda mendapatkan hasilnya:

{ "data": { "createTodo": { "id": 1, "due": "2023-12-31", "description": "Hello World!", "createdAt": "2023-11-14 20:47:11.875428" } } }

Pertanyaan. listTodos

Dari editor skema di konsol, di sisi kanan, pilih di testdb sebelahlistTodos(id: ID!): Todo. Handler permintaan menggunakan fungsi utilitas pilih untuk membangun permintaan secara dinamis pada waktu berjalan.

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) }

Kami ingin memfilter todos berdasarkan due tanggal. Mari kita perbarui resolver untuk memberikan due nilai ke. DATE Perbarui daftar impor dan penangan permintaan:

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 }; }

Mari kita coba query. Di editor Queries:

query LIST { listTodos(limit: 10, filter: {due: {between: ["2021-01-01", "2025-01-02"]}}) { items { id due description } } }

Mutasi. updateTodo

Anda juga bisa update aTodo. Dari editor Queries, mari kita perbarui Todo item pertama kami. id 1

mutation UPDATE { updateTodo(input: {id: 1, description: "edits"}) { description due id } }

Perhatikan bahwa Anda harus menentukan item id yang Anda perbarui. Anda juga dapat menentukan kondisi untuk hanya memperbarui item yang memenuhi kondisi tertentu. Misalnya, kami mungkin hanya ingin mengedit item jika deskripsi dimulai denganedits:

mutation UPDATE { updateTodo(input: {id: 1, description: "edits: make a change"}, condition: {description: {beginsWith: "edits"}}) { description due id } }

Sama seperti cara kami menangani create dan list operasi kami, kami dapat memperbarui resolver kami untuk mentransmisikan due bidang ke a. DATE Simpan perubahan ini keupdateTodo:

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]; }

Sekarang coba pembaruan dengan kondisi:

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 } }

Mutasi. deleteTodo

Anda bisa delete a Todo dengan deleteTodo mutasi. Ini berfungsi seperti updateTodo mutasi, dan Anda harus menentukan item id yang ingin Anda hapus:

mutation DELETE { deleteTodo(input: {id: 1}) { description due id } }

Menulis kueri khusus

Kami telah menggunakan utilitas rds modul untuk membuat SQL pernyataan kami. Kami juga dapat menulis pernyataan statis kustom kami sendiri untuk berinteraksi dengan database kami. Pertama, perbarui skema untuk menghapus id bidang dari CreateTask input.

input CreateTaskInput { todoId: Int! description: String }

Selanjutnya, buat beberapa tugas. Suatu tugas memiliki hubungan kunci asing denganTodo:

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 } }

Buat bidang baru dalam Query tipe Anda yang disebutgetTodoAndTasks:

getTodoAndTasks(id: Int!): Todo

Tambahkan tasks bidang ke Todo jenis:

type Todo { due: AWSDate! id: Int! createdAt: String description: String! tasks:TaskConnection }

Simpan skema. Dari editor skema di konsol, di sisi kanan, pilih Lampirkan Resolver untuk. getTodosAndTasks(id: Int!): Todo Pilih sumber RDS data Amazon Anda. Perbarui resolver Anda dengan kode berikut:

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; }

Dalam kode ini, kita menggunakan template sql tag untuk menulis SQL pernyataan bahwa kita dapat dengan aman meneruskan nilai dinamis pada waktu berjalan. createPgStatementdapat mengambil hingga dua SQL permintaan sekaligus. Kami menggunakannya untuk mengirim satu kueri untuk kami todo dan yang lain untuk kamitasks. Anda bisa melakukan ini dengan JOIN pernyataan atau metode lain dalam hal ini. Idenya adalah mampu menulis SQL pernyataan Anda sendiri untuk mengimplementasikan logika bisnis Anda. Untuk menggunakan kueri di editor Queries, kita dapat mencoba ini:

query TodoAndTasks { getTodosAndTasks(id: 2) { id due description tasks { items { id description } } } }

Menghapus klaster Anda

penting

Menghapus cluster bersifat permanen. Tinjau proyek Anda secara menyeluruh sebelum melakukan tindakan ini.

Untuk menghapus klaster Anda:

$ aws rds delete-db-cluster \ --db-cluster-identifier appsync-tutorial \ --skip-final-snapshot