Amazon Web Services ブログ

AWS Amplify の新機能 – AWS CDK 用に MySQL および PostgreSQL データベースをクエリする

12月20日、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 RDS データベースや Amazon Aurora データベースなどの GraphQL API 用のリレーショナルデータベースソースを使用したいと考えていました。今後、リレーショナルデータベースと DynamoDB データソースの両方のために、@model タイプの Amplify GraphQL API を使用できるようになりました。リレーショナルデータベースの情報は、別の schema.sql.graphql ファイルに生成されます。通常の schema.graphql ファイルを引き続き使用して、DynamoDB ベースのタイプを作成および管理できます。

MySQL または PostgreSQL データベースの情報を提供するだけで、仮想プライベートクラウド (VPC) の背後にある場合でも、インターネット上でパブリックにアクセスできる場合でも、AWS Amplify は、データベーステーブルに安全に接続して、作成、読み取り、更新、または削除 (CRUD) クエリおよびミューテーションを公開する、変更可能な GraphQL API を自動的に生成します。フロントエンドのために、データモデルの名前をより慣用的な名前に変更することもできます。一例として、データベーステーブルは「todos」(複数形、小文字) と呼ばれるが、クライアントには「ToDo」(単数形、パスカルケース) として公開される場合を挙げることができます。

1 行のコードで、既存の 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

Amplify の GraphQL API コンストラクトを新しい CDK プロジェクトにインストールします。

$ 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 コンソール[パラメータストア] に移動し、データベースの接続の詳細のパラメータ (hostname/urldatabase nameportusernamepassword など) を作成します。これらは、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 クラウドにデプロイします。

$ cdk deploy

これで、AWS AppSync コンソールに移動し、作成した GraphQL API を見つけることができます。

プロジェクトを選択し、[クエリ] メニューを選択します。MySQL データベースのテーブルと互換性のある、新しく作成された GraphQL API (1 つの項目を取得するための getMeals や、すべての項目を一覧表示するための listRestaurants など) を確認できます。

例えば、フィールドが addresscitynamephone_number などの項目を選択すると、新しい GraphQL クエリを確認できます。[実行] ボタンを選択すると、MySQL データベースからのクエリ結果が表示されます。

MySQL データベースをクエリすると、同じ結果が表示されます。

データベースに合わせて GraphQL スキーマをカスタマイズする方法
SQL でカスタムクエリまたはミューテーションを追加するには、生成された schema.sql.graphql ファイルを開き、the :<variable> 表記を使用してパラメータで @sql(statement: "") パスを使用します。

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

より長くて複雑な SQL クエリの場合は、customSqlStatements 設定オプションで SQL ステートメントを参照できます。参照値は、SQL ステートメントにマッピングされたプロパティの名前と一致する必要があります。次の例では、customSqlStatementssearchPosts プロパティが参照されています。

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

SQL ステートメントが API 定義でどのようにマッピングされるかを次に示します。

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
}

2 つのデータベーステーブル間の関係を作成する場合は、@hasOne ディレクティブと @hasMany ディレクティブを使用して 1:1 または 1:M の関係を確立します。関係の親に戻る双方向の関係を作成するには、@belongsTo ディレクティブを使用します。例えば、レストランとその食事メニューの間に 1:M の関係を作成できます。

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"])
     ...
}

DB インスタンスの GraphQL スキーマまたはデータベーススキーマに変更を加えるたびに、変更をクラウドにデプロイする必要があります。

DB インスタンスの GraphQL スキーマまたはデータベーススキーマに変更を加えるたびに、このガイドで前述した SQL スクリプトと .csv へのエクスポートのステップを再実行して、schema.sql.graphql ファイルを再生成し、変更をクラウドにデプロイする必要があります。

$ cdk deploy

詳細については、AWS Amplify ドキュメントの「Connect API to existing MySQL or PostgreSQL database」をご覧ください。

今すぐご利用いただけます
AWS Amplify のリレーショナルデータベースサポートは、Amazon VPC 内または AWS クラウド外の任意の場所でホストされている MySQL および PostgreSQL データベースで動作するようになりました。

ぜひお試しいただき、AWS Amplify の AWS re:Post、Amplify GraphQL API の GitHub リポジトリ、または通常の AWS サポートの連絡先を通じて、フィードバックをお寄せください。

Channy

P.S.サンプルコードの作成に貢献してくれた AWS の Principal Product Manager である René Huangtian Brandel に特に感謝します。

原文はこちらです。