AWS Lambda を使って Amazon Aurora Serverless からデータを配列で取得する

こんにちは、広野です。

サーバーレスアプリを開発していると、基本データベースは Amazon DynamoDB などの NoSQL を使用するのが王道なのですが、NoSQLでは対応しきれない要件のときにはやはり RDBMS を使用する局面もあります。

そんなとき、サーバーレスの RDBMS サービスである Amazon Aurora Serverless を積極的に使っていきたいのですが、AWS Lambda でデータを取得しようとするとデフォルトのままでは扱いづらい特殊なデータフォーマットになってしまいます。

この度、データフォーマットをシンプルな配列に加工する仕組みを検証しましたので紹介します。

やりたいこと

  • Amazon Aurora Serverless から AWS Lambda でデータを取得する。
  • データの取得には Data API を使用する。※Data API については以下リンクを参照
  • 最終的なデータの取得形式は、配列にしたい。
ERROR: The request could not be satisfied

実装方法

サンプルデータ

DB内には以下のようなテーブルがあるとしましょう。ここでは、このデータを全て取得してくるSQLを使用する想定です。

sampletable

id name number (数値型)
A001 いか 10
A002 たこ 20
B001 すし 30

加工前

AWS Lambda 関数 (Python)

import boto3
rds_client = boto3.client('rds-data')

def lambda_handler(event, context):
  # Database settings
  database_name = 'sampledatabase'
  db_cluster_arn = 'arn:aws:rds:ap-northeast-1:xxxxxxxxxxxx:cluster:samplecluster'
  db_credentials_secrets_store_arn = 'arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:rds-db-credentials/cluster-XXXXXXXXXXXXXXXXXXXXXXXXXX/xxxxxxxxxxxx'
  
  # Executing SQL
  def execute_statement(sql):
    response = rds_client.execute_statement(
      secretArn=db_credentials_secrets_store_arn,
      database=database_name,
      resourceArn=db_cluster_arn,
      sql=sql
    )
    return response

  # SQL実行結果をdataに格納
  data = execute_statement('select * from sampletable')
  # データをそのまま返す
  return data

結果データ

こんな感じの JSON データが返ってきます。

data[‘records’] にクエリーの結果データが格納されているのですが、データ型によって stringValue や longValue などといったキーが入った JSON データフォーマットになっており、非常に扱いづらいです。また、テーブルの列名は返ってきません。

{
  "ResponseMetadata": {
    "RequestId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "HTTPStatusCode": 200,
    "HTTPHeaders": {
      "x-amzn-requestid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "content-type": "application/json",
      "content-length": "xxx",
      "date": "Mon, 21 Mar 2022 00:00:00 GMT"
    },
    "RetryAttempts": 0
  },
  "numberOfRecordsUpdated": 0,
  "records": [
    [
      {
        "stringValue": "A001"
      },
      {
        "stringValue": "いか"
      },
      {
        "longValue": 10
      }
    ],
    [
      {
        "stringValue": "A002"
      },
      {
        "stringValue": "たこ"
      },
      {
        "longValue": 20
      }
    ],
    [
      {
        "stringValue": "B001"
      },
      {
        "stringValue": "すし"
      },
      {
        "longValue": 30
      }
    ]
  ]
}

これを、以下で加工します。

加工後

AWS Lambda 関数 (Python)

クエリー結果の data を加工する関数を追加し、return で返す前にフォーマットを変換しています。

import boto3
rds_client = boto3.client('rds-data')

def lambda_handler(event, context):
  # Database settings
  database_name = 'sampledatabase'
  db_cluster_arn = 'arn:aws:rds:ap-northeast-1:xxxxxxxxxxxx:cluster:samplecluster'
  db_credentials_secrets_store_arn = 'arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:rds-db-credentials/cluster-XXXXXXXXXXXXXXXXXXXXXXXXXX/xxxxxxxxxxxx'
  
  # Formatting query returned Field
  def formatField(field):
    return list(field.values())[0]
  # Formatting query returned Record
  def formatRecord(record):
    return [formatField(field) for field in record]
  # Formatting query returned Field
  def formatRecords(records):
    return [formatRecord(record) for record in records]
  # Executing SQL
  def execute_statement(sql):
    response = rds_client.execute_statement(
      secretArn=db_credentials_secrets_store_arn,
      database=database_name,
      resourceArn=db_cluster_arn,
      sql=sql
    )
    return response

  # SQL実行結果をdataに格納
  data = execute_statement('select * from sampletable')
  # 配列にフォーマットしたデータを返す
  return formatRecords(data['records'])

結果データ

スッキリしました!

これなら、アプリ側でも比較的扱いやすいです。連想配列ではないので、アプリで使用するときには列の並び順をきっちり押さえておく必要があります。

[
  [
    "A001",
    "いか",
    10
  ],
  [
    "A002",
    "たこ",
    20
  ],
  [
    "B001",
    "すし",
    30
  ]
]

IAM ロール

AWS Lambda 関数に付与する IAM ロールは、データを読み書きするのであればマネージドのRDSフルポリシーを付けておけばとりあえず動きますが、用途が明確になっているようでしたら Action や Resource 等をさらに制限しましょう。

マネージドポリシー

  • arn:aws:iam::aws:policy/AmazonRDSDataFullAccess
  • arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

まとめ

いかがでしたでしょうか?

エラー処理、ページネーション処理までは言及していないので実運用には物足りない内容かと思いますが、あくまでデータフォーマットの加工 TIPS としてお役に立てれば幸いです。

Amazon Aurora Serverless は今時点では RDS Proxy も未サポートなので、膨大なクエリーを受けるような環境では耐えられないかもしれません。比較的小規模で、重要性の低いユースケースであれば迷いなくオススメします。

著者について
広野 祐司

AWS サーバーレスアーキテクチャを駆使して社内クラウド人材育成アプリとコンテンツづくりに勤しんでいます。React で SPA を書き始めたら快適すぎて、他の言語には戻れなくなりました。サーバーレス & React 仲間を増やしたいです。AWSは好きですが、それよりもAWSすげー!って気持ちの方が強いです。
取得資格:AWS 認定は12資格、ITサービスマネージャ、ITIL v3 Expert 等
2020 - 2023 Japan AWS Top Engineer 受賞
2022 - 2023 Japan AWS Ambassador 受賞
2023 当社初代フルスタックエンジニア認定
好きなAWSサービス:AWS Amplify / AWS AppSync / Amazon Cognito / AWS Step Functions / AWS CloudFormation

広野 祐司をフォローする
クラウドに強いによるエンジニアブログです。
SCSKは専門性と豊富な実績を活かしたクラウドサービス USiZE(ユーサイズ)を提供しています。
USiZEサービスサイトでは、お客様のDX推進をワンストップで支援するサービスの詳細や導入事例を紹介しています。
AWSアプリケーション開発クラウドソリューションデータベース
シェアする
タイトルとURLをコピーしました