亚马逊AWS官方博客

AWS Amplify 新推出针对 AWS CDK 的 MySQL 和 PostgreSQL 数据库查询功能



今天,我们宣布正式发布一项新功能:支持通过 AWS Cloud Development Kit(AWS CDK)连接和查询您现有的 MySQL 数据库和 PostgreSQL 数据库,为 Amazon Web Services(AWS)内部或外部的关系数据库创建实时、安全的 GraphQL API。现在,您只需使用数据库端点和凭证,即可为关系数据库的所有操作生成完整的 API。当您的数据库架构发生变化时,您可以通过运行命令,应用最新的表架构更改。

2021 年,我们宣布推出了 AWS Amplify GraphQL Transformer 第 2 版,让即使只具有少量云技术专业知识开发人员也能够基于 GraphQL,开发功能丰富、灵活性高、可扩展性强的应用程序后端。这个新版本的 GraphQL Transformer 经过彻底重新设计,能够生成可扩展的管道解析器,以分发 GraphQL API 请求,应用业务逻辑(如授权),并与 Amazon DynamoDB 等底层数据来源进行通信。

然而,除了 Amazon DynamoDB 外,客户也希望使用 Amazon RDSAmazon Aurora关系数据库为 GraphQL API 提供数据来源。您现在可以将 @model 类型的 Amplify GraphQL API 用于关系数据库和 DynamoDB 这两种数据来源。关系数据库信息将生成到单独的 schema.sql.graphql 文件中。您可以继续使用常规的 schema.graphql 文件创建和管理 DynamoDB 支持的类型。

如果您仅提供 MySQL 或 PostgreSQL 数据库的信息,无论该数据库是隐藏在虚拟私有云(VPC)中,还是可通过互联网公开访问,AWS Amplify 都将自动生成可修改的 GraphQL API。该 API 可以安全地连接您的数据库表,并公开创建、读取、更新或删除 (CRUD)查询和变更。您也可以重命名数据模型,使其更符合前端命名习惯。例如,一个数据库表名为“todos”(复数,字母全部小写),但以“ToDo”(单数,帕斯卡命名法)这个名称公开给客户端。

只需一行代码,您就可以将任何现有的 Amplify GraphQL 授权规则添加到您的 API 中,以便无缝构建基于所有者的授权或公开只读模式等用例。生成的 API 基于 AWS AppSync 的 GraphQL 功能构建,因此提供现成可用的安全实时订阅功能。从任何数据模型订阅任何 CRUD 事件也只需几行代码。

在 AWS CDK 中利用 MySQL 数据库开始使用
AWS CDK 允许您使用编程语言强大的表达能力,在云端构建可靠、可扩展、经济实惠的应用程序。若要开始使用,请在本地计算机上安装 AWS CDK

$ npm install -g aws-cdk

运行以下命令,验证安装是否正确,并打印 AWS CDK 的版本号。

$ cdk –version

接下来,为您的应用程序创建一个新目录:

$ mkdir amplify-api-cdk
$ cd amplify-api-cdk

使用 cdk init 命令初始化 CDK 应用程序。

$ cdk init app --language typescript

在新的 CDK 项目中安装 Amplify 的 GraphQL API 架构:

$ npm install @aws-amplify/graphql-api-construct

打开 CDK 项目中的主堆栈文件(路径通常为 lib/<your-project-name>-stack.ts)。在文件顶部导入必要的架构:

import {
    AmplifyGraphqlApi,
    AmplifyGraphqlDefinition
} from '@aws-amplify/graphql-api-construct';

通过在您的 MySQL 数据库中执行以下 SQL 语句,为新的关系数据库 API 生成 GraphQL 架构。请确保将结果输出到 .csv 文件中,其中应包含列标题,然后将 <database-name> 替换为数据库或/和架构的名称。

SELECT
  INFORMATION_SCHEMA.COLUMNS.TABLE_NAME,
  INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME,
  INFORMATION_SCHEMA.COLUMNS.COLUMN_DEFAULT,
  INFORMATION_SCHEMA.COLUMNS.ORDINAL_POSITION,
  INFORMATION_SCHEMA.COLUMNS.DATA_TYPE,
  INFORMATION_SCHEMA.COLUMNS.COLUMN_TYPE,
  INFORMATION_SCHEMA.COLUMNS.IS_NULLABLE,
  INFORMATION_SCHEMA.COLUMNS.CHARACTER_MAXIMUM_LENGTH,
  INFORMATION_SCHEMA.STATISTICS.INDEX_NAME,
  INFORMATION_SCHEMA.STATISTICS.NON_UNIQUE,
  INFORMATION_SCHEMA.STATISTICS.SEQ_IN_INDEX,
  INFORMATION_SCHEMA.STATISTICS.NULLABLE
      FROM INFORMATION_SCHEMA.COLUMNS
      LEFT JOIN INFORMATION_SCHEMA.STATISTICS ON INFORMATION_SCHEMA.COLUMNS.TABLE_NAME=INFORMATION_SCHEMA.STATISTICS.TABLE_NAME AND INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME=INFORMATION_SCHEMA.STATISTICS.COLUMN_NAME
      WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_SCHEMA = '<database-name>';

运行以下命令,将 <path-schema.csv> 替换为在上一步中创建的 .csv 文件的路径。

$ npx @aws-amplify/cli api generate-schema \
    --sql-schema <path-to-schema.csv> \
    --engine-type mysql –out lib/schema.sql.graphql

您可以打开 schema.sql.graphql 文件,查看从 MySQL 数据库架构导入的数据模型。

input AMPLIFY {
     engine: String = "mysql"
     globalAuthRule: AuthRule = {allow: public}
}

type Meals @model {
     id: Int! @primaryKey
     name: String!
}

type Restaurants @model {
     restaurant_id: Int! @primaryKey
     address: String!
     city: String!
     name: String!
     phone_number: String!
     postal_code: String!
     ...
}

如果您尚未完成,请前往 AWS Systems Manager 控制台中的参数存储部分,为数据库连接的详细信息(如主机名称/URL数据库名称端口用户名密码)创建参数。在下一步,Amplify 需要这些信息才能成功连接您的数据库,并对其执行 GraphQL 查询或变更。

在主堆栈类中,添加以下代码,定义新的 GraphQL API。将 dbConnectionConfg 选项替换为在上一步中创建的参数路径。

new AmplifyGraphqlApi(this, "MyAmplifyGraphQLApi", {
  apiName: "MySQLApi",
  definition: AmplifyGraphqlDefinition.fromFilesAndStrategy(
    [path.join(__dirname, "schema.sql.graphql")],
    {
      name: "MyAmplifyGraphQLSchema",
      dbType: "MYSQL",
      dbConnectionConfig: {
        hostnameSsmPath: "/amplify-cdk-app/hostname",
        portSsmPath: "/amplify-cdk-app/port",
        databaseNameSsmPath: "/amplify-cdk-app/database",
        usernameSsmPath: "/amplify-cdk-app/username",
        passwordSsmPath: "/amplify-cdk-app/password",
      },
    }
  ),
  authorizationModes: { apiKeyConfig: { expires: cdk.Duration.days(7) } },
  translationBehavior: { sandboxModeEnabled: true },
});

此配置假设您的数据库可通过互联网访问。此外,AWS AppSync 的默认授权模式已设置为 Api 密钥,并启用了沙盒模式,使所有模型均可被公开访问。这有助于您在添加更精细的授权规则之前,对 API 进行测试。

最后,将您的 GraphQL API 部署到 AWS Cloud。

$ cdk deploy

现在,您可以前往 AWS AppSync 控制台,找到您创建的 GraphQL API。

选择您的项目和查询菜单。您可以看到新创建的,并与您的 MySQL 数据库表兼容的 GraphQL API,例如,用于获取一个项目的 getMeals,或用于列出所有项目的 listRestaurants

举例而言,当您选择包含 addresscitynamephone_number 等字段的项目时,可以看到新的 GraphQL 查询。选择运行按钮,即可看到来自 MySQL 数据库的查询结果。

如果您查询 MySQL 数据库,可以看到相同的结果。

如何为数据库自定义 GraphQL 架构
要在您的 SQL 中添加自定义查询或变更,请打开生成的 schema.sql.graphql 文件,然后通过 @sql(statement: "") 传入使用 :<variable> 表示法的参数。

type Query {
     listRestaurantsInState(state: String): Restaurants @sql("SELECT * FROM Restaurants WHERE state = :state;”)
}

对于较长、较复杂的 SQL 查询,您可以在 customSqlStatements 配置选项中引用 SQL 语句。引用值必须与映射到 SQL 语句的属性名称相匹配。以下示例引用了 customSqlStatements 中的 searchPosts 属性:

type Query {
      searchPosts(searchTerm: String): [Post]
      @sql(reference: "searchPosts")
}

以下是在 API 定义中映射 SQL 语句的方式。

new AmplifyGraphqlApi(this, "MyAmplifyGraphQLApi", { 
    apiName: "MySQLApi",
    definition: AmplifyGraphqlDefinition.fromFilesAndStrategy( [path.join(__dirname, "schema.sql.graphql")],
    {
        name: "MyAmplifyGraphQLSchema",
        dbType: "MYSQL",
        dbConnectionConfig: {
        //	...ssmPaths,
     }, customSqlStatements: {
        searchPosts: // property name matches the reference value in schema.sql.graphql 
        "SELECT * FROM posts WHERE content LIKE CONCAT('%', :searchTerm, '%');",
     },
    }
  ),
//...
});

SQL 语句将像在架构中以内联方式定义过一样执行。在使用参数、确保 SQL 语法有效,以及匹配返回类型方面,同样的规则也适用。使用引用文件可保持架构的整洁,并允许跨字段复用 SQL 语句。对于较长、较复杂的 SQL 查询,这是最佳做法。

或者,您也可以使用 @refersTo 指令更改字段和模型的名称。如果您未提供 @refersTo 指令,AWS Amplify 将假设模型和字段的名称与数据库表和列的名称完全匹配。

type Todo @model @refersTo(name: "todos") {
     content: String
     done: Boolean
}

如果您想在两个数据库表之间创建关系,请使用 @hasOne@hasMany 指令建立一对一或一对多关系。使用 @belongsTo 指令可创建指向关系父项的双向关系。例如,您可以在餐厅与它的餐单之间建立一对多关系。

type Meals @model {
     id: Int! @primaryKey
     name: String!
     menus: [Restaurants] @hasMany(references: ["restaurant_id"])
}

type Restaurants @model {
     restaurant_id: Int! @primaryKey
     address: String!
     city: String!
     name: String!
     phone_number: String!
     postal_code: String!
     meals: Meals @belongsTo(references: ["restaurant_id"])
     ...
}

每当您更改了 GraphQL 架构或数据库实例中的数据库架构,都应将更改部署到云端:

每当您更改了 GraphQL 架构或数据库实例中的数据库架构,都应重新运行 SQL 脚本,并再次执行本指南前面提到的导出到 .csv 的步骤,以重新生成 schema.sql.graphql,然后将您的更改部署到云端:

$ cdk deploy

要了解更多信息,请参阅 AWS Amplify 文档中的《将 API 连接到现有的 MySQL 或 PostgreSQL 数据库》

现已推出
AWS Amplify 现在已经支持关系数据库,能够与部署在 Amazon VPC 内部,甚至 AWS Cloud 外部的任何 MySQL 数据库或 PostgreSQL 数据库协同工作。

不妨做出尝试,并将反馈发送至 AWS Amplify 的 AWS re:Post、Amplify GraphQL API 的 GitHub 存储库。或者,您也可以通过您常用的 AWS Support 联系方式提交反馈。

Channy

附言:特别感谢 AWS 首席产品经理 René Huangtian Brandel 编写的示例代码。