AWS CLI で DynamoDB のデータ型記述子なしに複数 json データ投入

に公開

TL;DR

  • DynamoDB の "N" や "S" などのデータ型記述子をもたない生の json データを複数投入する shell のワンライナーを作りました
bash
TABLE="<YOUR TABLE>"
JSON_FILE="<YOUR JSON FILE NAME>"
# json の配列を要素(record)に分解して、" を ' に置換してデータ投入
jq -c '.[]' "${JSON_FILE}" | sed -e "s/\"/'/g" \
  | while read -r record; do aws dynamodb execute-statement --statement "INSERT INTO ${TABLE} value ${record}"; done

この記事を読んで欲しい人

  • AWS CLI から DynamoDB に複数の生 json データを投入したい人

前提

本記事では、下記を前提とします。

  • aws コマンドが使える環境があること
  • jq コマンドが使える環境であること
  • DynamoDB に触れたことがあり、基本的な知識があること

DynamoDB への json データ投入なんか面倒じゃないか...?

最近、勉強のために DynamoDB を触っており、サンプルデータの投入をやろうとして、json データの投入方法を軽く調べたのですが、既存の方法では次のようなアプローチが知られているようでした。

  1. AWS CLI を使って、"N" や "S" などのDynamoDB データ記述子をもつ独自の json ファイルを作成してデータを投入

https://qiita.com/yamamoto_y/items/b9393560a744137a86cb

  1. python などのスクリプトを書いて、データ投入

https://note.com/taro1212/n/na7a17a468bf4

両者とも素晴らしい情報を共有して頂いている記事なのですが、私はこれらのアプローチに次の課題があると感じました。

    1. の方法は、DynamoDB データ記述子をもつ json ファイルを作るのが面倒。また、1回のコマンドで、24件までしかデータが投入できない制約がある。
    1. 実装量は多くないがちょっとしたデータ投入をするために、python 等の言語環境を用意するのは手間。shell で済ませたい。

さらに調べてみると、DynamoDB shell と PartiQL というものがあることがわかりました。

https://zenn.dev/lambta/articles/cbaf1695cfc291

こちらの記事を読んだところ、AWS CLI から PartiQL を利用することで課題解決ができそうなことがわかりました。

しかし、PartiQL は複数 json データ(json の配列)を一括投入する VALUES句は提供していなさそうだったので、shell でデータ数分のコマンドをループ実行することにしました。

実際にデータ投入してみる

サンプルデータを用意して、実際に json データの投入をやってみます。

データ例

例として、部門が管理するデータ?みたいなものを扱います。
サンプルデータは、3階層程度のネストをもつように LLM にお願いして作成しました。

department.json
[
  {
    "department": "開発部",
    "projects": [
      {
        "name": "プロジェクトA",
        "tasks": [
          {
            "id": 1,
            "title": "API設計"
          },
          {
            "id": 2,
            "title": "DBスキーマ作成"
          }
        ]
      },
      {
        "name": "プロジェクトB",
        "tasks": [
          {
            "id": 3,
            "title": "UIプロトタイプ作成"
          },
          {
            "id": 4,
            "title": "テストケース設計"
          }
        ]
      }
    ]
  },
  {
    "department": "営業部",
    "projects": [
      {
        "name": "新規顧客開拓",
        "tasks": [
          {
            "id": 5,
            "title": "見積書作成"
          },
          {
            "id": 6,
            "title": "プレゼン資料準備"
          }
        ]
      }
    ]
  }
]

データ投入先の DynamoDB は下記の条件で作成しました。

  • DynamoDB のデータ投入先テーブル
    • AWS コンソール上から、テーブル名 Departmentを作成
    • department (S型)をハッシュキーに設定

コマンド実行例

データ投入実施

bash
# json の配列を要素(record)毎に分解して、" を ' に置換してデータ投入
jq -c '.[]' department.json | sed -e "s/\"/'/g" \
  | while read -r record; do aws dynamodb execute-statement --statement "INSERT INTO Department value ${record}"; done
stdout
{
    "Items": []
}
{
    "Items": []
}

データ投入確認

bash
aws dynamodb execute-statement --statement "SELECT * FROM Department;"
stdout
{
    "Items": [
        {
            "department": {
                "S": "営業部"
            },
            "projects": {
                "L": [
                    {
                        "M": {
                            "name": {
                                "S": "新規顧客開拓"
                            },
                            "tasks": {
                                "L": [
                                    {
                                        "M": {
                                            "id": {
                                                "N": "5"
                                            },
                                            "title": {
                                                "S": "見積書作成"
                                            }
                                        }
                                    },
                                    {
                                        "M": {
                                            "id": {
                                                "N": "6"
                                            },
                                            "title": {
                                                "S": "プレゼン資料準備"
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                ]
            }
        },
        {
            "department": {
                "S": "開発部"
            },
            "projects": {
                "L": [
                    {
                        "M": {
                            "name": {
                                "S": "プロジェクトA"
                            },
                            "tasks": {
                                "L": [
                                    {
                                        "M": {
                                            "id": {
                                                "N": "1"
                                            },
                                            "title": {
                                                "S": "API設計"
                                            }
                                        }
                                    },
                                    {
                                        "M": {
                                            "id": {
                                                "N": "2"
                                            },
                                            "title": {
                                                "S": "DBスキーマ作成"
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    },
                    {
                        "M": {
                            "name": {
                                "S": "プロジェクトB"
                            },
                            "tasks": {
                                "L": [
                                    {
                                        "M": {
                                            "id": {
                                                "N": "3"
                                            },
                                            "title": {
                                                "S": "UIプロトタイプ作成"
                                            }
                                        }
                                    },
                                    {
                                        "M": {
                                            "id": {
                                                "N": "4"
                                            },
                                            "title": {
                                                "S": "テストケース設計"
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                ]
            }
        }
    ]
}

SELECTで取得した json は DynamoDB のデータ記述子を含んで出力されました。こちらもデータ記述子を含まない json で出力したいところですが、今後の課題とします。

まとめ

本記事では、AWS CLI の PartiQL を利用して、複数の json をデータ投入可能な shell ワンライナーを取り扱いました。
DynamoDB へのデータ投入で困っていた人の助けとなれば幸いです。

PartiQL に関しては SQL に慣れた開発者であれば、DynamoDB でも見慣れたクエリを使えて便利そうなので、今後より詳しく勉強していきたいと思いました。

ぬまごたつ

Discussion