DynamoDBのテーブルにCSVファイルから一括でデータをimportしてみた

CSVを有効活用したかったのです
2020.08.30

こんにちは、崔です。

CSVファイルのデータをDynamoDBのテーブルにimportしたいと思ったことはありませんか?
こちらのAWSの公式ブログにおいて、これを実装するCloudFormationのテンプレートが提供されていましたので、試してみました。

やってみた

上記ブログ内のリポジトリからテンプレートをダウンロードします。

GitHub リポジトリ

CSVToDynamo.templateファイル内の AttributeName の2箇所のパーティションキー名を uuid から利用予定のパーティションキー名に変更します。

    "Resources": {
        "DynamoDBTable":{
            "Type": "AWS::DynamoDB::Table",
            "Properties":{
                "TableName": {"Ref" : "DynamoDBTableName"},
                "BillingMode": "PAY_PER_REQUEST",
                "AttributeDefinitions":[
                    {
                        "AttributeName": "uuid",
                        "AttributeType": "S"
                    }
                ],
                "KeySchema":[
                    {
                        "AttributeName": "uuid",
                        "KeyType": "HASH"
                    }
                ],
                "Tags":[
                    {
                        "Key": "Name",
                        "Value": {"Ref" : "DynamoDBTableName"}
                    }
                ]
            }
        },

次にCloudFormationからこのテンプレートを選択します。

パラメーターに、

  • CSVファイル名(FileName)
  • CSVファイルをアップロードするS3バケット名(BucketName)
  • DynamoDBのテーブル名(DynamoDBTableName)

を入力して、実行します。

CloudFormationが正常に終了すると、空のDynamoDBのテーブルとS3バケット、Lambdaファンクションが作成されます。

作成されたLambdaファンクションは次のものでした。

import json
import boto3
import os
import csv
import codecs
import sys

s3 = boto3.resource('s3')
dynamodb = boto3.resource('dynamodb')

bucket = os.environ['bucket']
key = os.environ['key']
tableName = os.environ['table']

def lambda_handler(event, context):


   #get() does not store in memory
   try:
       obj = s3.Object(bucket, key).get()['Body']
   except:
       print("S3 Object could not be opened. Check environment variable. ")
   try:
       table = dynamodb.Table(tableName)
   except:
       print("Error loading DynamoDB table. Check if table was created correctly and environment variable.")

   batch_size = 100
   batch = []

   #DictReader is a generator; not stored in memory
   for row in csv.DictReader(codecs.getreader('utf-8')(obj)):
      if len(batch) >= batch_size:
         write_to_dynamo(batch)
         batch.clear()

      batch.append(row)

   if batch:
      write_to_dynamo(batch)

   return {
      'statusCode': 200,
      'body': json.dumps('Uploaded to DynamoDB Table')
   }


def write_to_dynamo(rows):
   try:
      table = dynamodb.Table(tableName)
   except:
      print("Error loading DynamoDB table. Check if table was created correctly and environment variable.")

   try:
      with table.batch_writer() as batch:
         for i in range(len(rows)):
            batch.put_item(
               Item=rows[i]
            )
   except:
      print("Error executing batch_writer")

次のようなCSVを用意しました。最初のカラムには、パーティションキーを指定します。

"Id","Price","ProductCategory","Title","BicycleType","Brand","Color","Description","Authors","Dimensions","ISBN","InPublication","PageCount"
"101","2","Book","Book 101 Title",,,,,"[  { ""S"" : ""Author1"" }]","8.5 x 11.0 x 0.5","111-1111111111","true","500"
"102","20","Book","Book 102 Title",,,,,"[  { ""S"" : ""Author1"" },  { ""S"" : ""Author2"" }]","8.5 x 11.0 x 0.8","222-2222222222","true","600"
"103","2000","Book","Book 103 Title",,,,,"[  { ""S"" : ""Author1"" },  { ""S"" : ""Author2"" }]","8.5 x 11.0 x 1.5","333-3333333333","false","600"
"201","100","Bicycle","18-Bike-201","Road","Mountain A","[  { ""S"" : ""Red"" },  { ""S"" : ""Black"" }]","201 Description",,,,,
"202","200","Bicycle","21-Bike-202","Road","Brand-Company A","[  { ""S"" : ""Green"" },  { ""S"" : ""Black"" }]","202 Description",,,,,
"203","300","Bicycle","19-Bike-203","Road","Brand-Company B","[  { ""S"" : ""Red"" },  { ""S"" : ""Green"" },  { ""S"" : ""Black"" }]","203 Description",,,,,
"204","400","Bicycle","18-Bike-204","Mountain","Brand-Company B","[  { ""S"" : ""Red"" }]","204 Description",,,,,
"205","500","Bicycle","18-Bike-204","Hybrid","Brand-Company C","[  { ""S"" : ""Red"" },  { ""S"" : ""Black"" }]","205 Description",,,,,

これを先程のS3バケットにアップロードします。

すると、DynamoDBのテーブルにデータがロードされました。

まとめ

非常に簡単にCSVファイルをDynamoDBのテーブルにimportすることができました。
簡単に試せるので、まずはこの方法でimportできるか実行してみては如何でしょうか。