JavaScript Amazon RDS 的解析器函数参考 - Amazon AppSync
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

JavaScript Amazon RDS 的解析器函数参考

Amazon AppSync RDS 函数和解析器允许开发人员使用 RDS 数据 API 向 Amazon Aurora 集群数据库发送SQL查询,并获取这些查询的结果。您可以使用带有模块sql标签的模板或使用rds模块 Amazon AppSync的selectinsert、和remove帮助函数来编写发送到 Data API 的SQL语句。rds update Amazon AppSync 利用 RDS 数据服务的ExecuteStatement操作对数据库运行 SQL 语句。

带 SQL 标签的模板

Amazon AppSync的sql标记模板使您能够使用模板表达式创建可在运行时接收动态值的静态语句。 Amazon AppSync 根据表达式值构建变量映射以构造发送到 Amazon Aurora 无服务器数据 API 的SqlParameterized查询。使用此方法,运行时传递的动态值不可能修改原始语句,这可能会导致意外执行。所有动态值都作为参数传递,不能修改原始语句,也不会由数据库执行。这使您的查询不太容易受到 SQL 注入攻击。

注意

在所有情况下,在编写 SQL 语句时,都应遵循安全准则,以正确处理作为输入收到的数据。

注意

sql 标签的模板仅支持传递变量值。不能使用表达式来动态指定列名称或表名称。但是,您可以使用实用程序函数来构建动态语句。

在以下示例中,我们创建了一个查询,该查询根据运行时在 GraphQL 查询中动态设置的 col 参数值进行筛选。只能使用标签表达式将该值添加到语句中:

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

借助于通过变量映射传递所有动态值,我们依靠数据库引擎来安全地处理和清理值。

创建语句

函数和解析器可以与 MySQL 和 PostgreSQL 数据库进行交互。分别使用 createMySQLStatementcreatePgStatement 来构建语句。例如,createMySQLStatement 可以创建 MySQL 查询。这些函数最多可接受两条语句,在请求应立即检索结果时很有用。使用 MySQL,您可以执行:

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); }
注意

createPgStatementcreateMySQLStatement 不转义或引用使用带 sql 标签的模板构建的语句。

检索数据

您执行的 SQL 语句的结果可在响应处理程序的 context.result 对象中提供。结果是一个 JSON 字符串,其中包含来自 ExecuteStatement 操作的响应元素。解析后,结果具有以下形状:

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

您可以使用 toJsonObject 实用程序将结果转换为表示返回行的 JSON 对象列表。例如:

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

请注意,toJsonObject 返回语句结果数组。如果您提供了一条语句,则数组长度为 1。如果您提供了两条语句,则数组长度为 2。数组中的每个结果都包含 0 行或多行。如果结果值无效或不符合预期,则 toJsonObject 返回 null

实用程序函数

您可以使用 Amazon AppSync RDS 模块的实用工具帮助程序与您的数据库进行交互。

SQL 选择

select 实用程序会创建一条 SELECT 语句来查询您的关系数据库。

基本用法

在其基本形式中,您可以指定要查询的表:

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

请注意,您也可以在表标识符中指定架构:

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

指定列

您可以使用 columns 属性指定列。如果未将其设置为某个值,则它默认为 *

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

您也可以指定列的表:

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

限制和偏移

您可以将 limitoffset 应用于查询:

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

排序依据

您可以使用 orderBy 属性对结果进行排序。提供指定列和可选 dir 属性的对象数组:

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

筛选器

您可以使用特殊条件对象来构建筛选条件:

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

您也可以组合筛选条件:

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

您也可以创建 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 } } ]} })); }

您也可以使用 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 } } ]} })); }

您也可以使用以下运算符来比较值:

运算符 描述 可能的值类型
eq Equal 数字、字符串、布尔值
没有 Not equal 数字、字符串、布尔值
le Less than or equal 数字,字符串
lt Less than 数字,字符串
ge Greater than or equal 数字,字符串
gt Greater than 数字,字符串
contains 喜欢 字符串
不包含 不像 字符串
开始于 以前缀开头 字符串
介于 在两个值之间 数字,字符串
属性存在 该属性不为空 数字、字符串、布尔值
size 检查元素的长度 字符串

SQL 插入

insert 实用程序提供了一种通过 INSERT 操作在数据库中插入单行项目的简单方法。

单个项目插入

要插入项目,请指定表,然后传入您的值对象。对象键映射到您的表列。列名称会自动转义,并使用变量映射将值发送到数据库:

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

MySQL 用例

您可以组合 insert 后跟 select 来检索您插入的行:

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

Postgres 用例

借助 Postgres,您可以使用 returning 从插入的行中获取数据。它接受 * 或列名称数组:

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

SQL 更新

update 实用程序允许您更新现有行。您可以使用条件对象将更改应用于满足条件的所有行中的指定列。例如,假设我们有一个允许我们进行这种突变的架构。我们要将 Personname 更新为 id3,但仅限我们自 2000 年开始就已知道它们 (known_since):

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

更新解析器如下所示:

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

我们可以在条件中添加一项检查,以确保只更新主键 id 等于 3 的行。同样,对于 Postgres inserts,您可以使用 returning 返回修改后的数据。

SQL 删除

remove 实用程序允许您删除现有行。您可以在满足条件的所有行上使用条件对象。请注意,delete这是中的保留关键字 JavaScript。 remove应该改用:

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

转换

在某些情况下,您可能希望在语句中使用更具体的正确对象类型。您可以使用提供的类型提示来指定参数的类型。 Amazon AppSync 支持与数据 API 相同的类型提示。你可以使用 Amazon AppSync rds模块中的typeHint函数来转换参数。

以下示例允许您将数组作为强制转换为 JSON 对象的值发送。我们使用 -> 运算符来检索 JSON 数组中 index2 的元素:

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 }

在处理和比较 DATETIMETIMESTAMP 时,强制转换也很有用:

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

下面是另一个示例,显示如何发送当前日期和时间:

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

可用的类型提示

  • typeHint.DATE – 相应的参数作为 DATE 类型的对象发送到数据库。接受的格式为 YYYY-MM-DD

  • typeHint.DECIMAL – 相应的参数作为 DECIMAL 类型的对象发送到数据库。

  • typeHint.JSON – 相应的参数作为 JSON 类型的对象发送到数据库。

  • typeHint.TIME – 相应的字符串参数值作为 TIME 类型的对象发送到数据库。接受的格式为 HH:MM:SS[.FFF]

  • typeHint.TIMESTAMP – 相应的字符串参数值作为 TIMESTAMP 类型的对象发送到数据库。接受的格式为 YYYY-MM-DD HH:MM:SS[.FFF]

  • typeHint.UUID – 相应的字符串参数值作为 UUID 类型的对象发送到数据库。