DynamoDB 데이터에서 CSV를 만들어 S3으로 올리는 Lambda 함수

경위



직장에서 DynamoDB를 사용하게 되고, 그 중에서 「일차로 DynamoDB의 데이터를 txt 파일로 내보내어 소정의 S3 버킷에 둔다(일마다 파일을 나누는)」라는 요건이 있어, 방법을 조사해 구현해 보았다.

전체 설계



CloudWatchEvent를 사용하는 일반적인 일일 처리 구성.
Dynamo의 항목이 날짜를 가지고 있기 때문에 그 날짜를 조건으로 그 날 내보내는 데이터를 Query 해 온다.


조사한 것 외에 DynamoDB 스트림 좋아요? 라고 생각했기 때문에 이번의 방법을 취했다.
이 근처 실제로는 어떨지는 모르기 때문에, 자세한 쪽은 꼭 말해 주세요( ^) o(^ )

테이블



이런 느낌.
Dynamo에서는 Query의 조건으로 할 수 있는 것은 key 항목인 것 같다.
그런데 조건에 지정하고 싶었던 date가 key 항목이 아니었기 때문에 date를 키로 한 인덱스( GSI )를 작성했다.


id(Hash key)
count(Range Key)
date


a1
1
20170101

a1
2
20170101

a1
3
20170101

b1
1
20170102

b1
2
20170102

c1
1
20170102


Lambda 함수



이런 느낌.
IAM 롤의 설정은 할애. 좋은 느낌을 받았습니다.

index.js
'use strict'
const AWS = require('aws-sdk');
const moment = require('moment');
const fs = require('fs');

AWS.config.update({ region: 'ap-northeast-1' });

const docClient = new AWS.DynamoDB.DocumentClient();
const s3 = new AWS.S3();

exports.handler = function (event, context, callback) {

    let params = {
        TableName: "dynamo_toS3",
        IndexName: "date-count-index",
        KeyConditionExpression: "#date = :date",
        ExpressionAttributeNames: {
            "#date": "date"
        },
        ExpressionAttributeValues: {
            ":date": moment().format('YYYYMMDD') //バッチ実行日に作成されたレコードのみ取得
        }
    };

    docClient.query(params).promise().then(data => {

        let logArray =[];

        data.Items.forEach(element => {

            logArray.push(JSON.stringify(element));

        });

        return new Promise(function(resolve, reject) {
      
       //Lambdaでは一時的なファイルの出力先に/tmpが使える
            fs.writeFile('/tmp/tmp.txt', logArray.join('\n'), function(err) { 
                if (err) reject(err);
                else resolve(data);
            });
        });

    }).then(() => {

        let s3Params = {
            Bucket: "my-bucket",
            Key: `log_${moment().format('YYYYMMDD')}.txt`,
            Body: fs.readFileSync('/tmp/tmp.txt')
        }

        return s3.putObject(s3Params).promise();

    }).then(data => {

        console.log(data);

    })
    .catch(err => {

        console.log(err);
    })

};


요약 또는 소감



평소 RDB에 익숙해지고 있는 몸으로 하면, Dynamo는 약간 버릇이 있는 것처럼 느낀다.
여기 의 기사에도 있는 대로 SDK를 사용하는 경우는 AWS.DynamoDB보다 AWS.DynamoDB.DocumentClient를 사용하는 것이 좋다.
다음은 DynamoDB Stream을 트리거로 한 것도 시도하고 싶다.

좋은 웹페이지 즐겨찾기