Amazon DynamoDBはAWSクラウド上だけでなくローカルでも実行できるバージョン(DynamoDBローカル)が提供されている。ローカルで実行することにより課金を気にせず動作確認や開発が可能になる。
ここではUbuntu 18.04にDynamoDBローカルを導入してテーブルの作成やデータの操作を行ってみる。

DynamoDBローカル動作環境

DynamoDBローカルはjarファイルとDockerイメージの2種類が提供されているが、ここでは前者の方法で確認する。

jarファイルを利用する場合はあらかじめ以下をインストールしておく。

⦿ Java Runtime Environment (JRE) 6.x 以降

DynamoDBローカルインストール

まず以下からDynamoDBローカルのtar.gzをダウンロードする。

ダウンロードしたら任意の場所に展開する。インストールはこれだけである。

$ tar zxvf dynamodb_local_latest.tar.gz

DynamoDBローカルサーバ起動

サーバの起動も簡単で、以下のようにすればよい。Ctrl + cで停止する。

$ java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb
Initializing DynamoDB Local with the following configuration:
Port:   8000
InMemory:   false
DbPath: null
SharedDb:   true
shouldDelayTransientStatuses:   false
CorsParams:   *

尚、デフォルトの待受ポートは8000なので必要に応じて変更する。(-port <n>で指定)

テーブル作成

サーバの起動ができたら実際にテーブルを作成してみる。

AWS CLIを使って以下のようにする。ここでは「test」というテーブルを作り、キーを「num」とする。

$ aws dynamodb create-table --table-name test \
--attribute-definitions AttributeName=num,AttributeType=N \
--key-schema AttributeName=num,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 \
--endpoint-url http://localhost:8000
{
    "TableDescription": {
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/test", 
        "AttributeDefinitions": [
            {
                "AttributeName": "num", 
                "AttributeType": "N"
            }
        ], 
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0, 
            "WriteCapacityUnits": 1, 
            "LastIncreaseDateTime": 0.0, 
            "ReadCapacityUnits": 1, 
            "LastDecreaseDateTime": 0.0
        }, 
        "TableSizeBytes": 0, 
        "TableName": "test", 
        "BillingModeSummary": {
            "LastUpdateToPayPerRequestDateTime": 0.0, 
            "BillingMode": "PROVISIONED"
        }, 
        "TableStatus": "ACTIVE", 
        "KeySchema": [
            {
                "KeyType": "HASH", 
                "AttributeName": "num"
            }
        ], 
        "ItemCount": 0, 
        "CreationDateTime": 1571411233.367
    }
}

テーブルができていることを確認する。

$ aws dynamodb list-tables --endpoint-url http://localhost:8000
{
    "TableNames": [
        "test"
    ]
}

データ操作

テーブルが作成できたらデータを挿入/更新/削除してみる。

⦿ データ挿入

$ aws dynamodb put-item --table-name test \
--item '{"num":{"N":"1"},"data":{"S":"first"}}' \
--endpoint-url http://localhost:8000

⦿ データ取得

$ aws dynamodb get-item --table-name test \
--key '{"num":{"N":"1"}}' \
--endpoint-url http://localhost:8000
{
    "Item": {
        "num": {
            "N": "1"
        }, 
        "data": {
            "S": "first"
        }
    }

AWS CLIだけでなくブラウザからアクセスしてJavaScriptで操作することもできるので、以降はブラウザ上で実行する。

http://localhost:8000/shell/

⦿ データ挿入

左ペインに以下のコードを入力し、実行ボタン(▶)をクリックすると右ペインに実行結果が表示される。

AWS.config.endpoint = new AWS.Endpoint('http://localhost:8000');
var dynamodb = new AWS.DynamoDB();
var params = {
    TableName: 'test',
    Item: {
        'num':{N: '2'},
        'data':{S: 'second'}
    }
};
dynamodb.putItem(params, function(err, data) {
    if(err) {
        console.log(err, err.stack);
    } else {
        console.log(data);
    }
});

⦿ データ取得

AWS.config.endpoint = new AWS.Endpoint('http://localhost:8000');
var dynamodb = new AWS.DynamoDB();
var params = {
    TableName: 'test',
    Key: {
        'num':{N: '2'}
    }
};
dynamodb.getItem(params, function(err, data) {
    if(err) {
        console.log(err, err.stack);
    } else {
        console.log(data);
    }
});

⦿ データ更新

AWS.config.endpoint = new AWS.Endpoint('http://localhost:8000');
var dynamodb = new AWS.DynamoDB();
var params = {
    TableName: 'test',
    Key: {
        'num':{N: '2'}
    },
    ExpressionAttributeNames: {
        '#d': 'data'
    },
    ExpressionAttributeValues: {
        ':newData':{S: '2nd'}
    },
    UpdateExpression: 'SET #d = :newData'
};
dynamodb.updateItem(params, function(err, data) {
    if(err) {
        console.log(err, err.stack);
    } else {
        console.log(data);
    }
});

⦿ データ削除

AWS.config.endpoint = new AWS.Endpoint('http://localhost:8000');
var dynamodb = new AWS.DynamoDB();
var params = { 
    TableName: 'test',
    Key: {
        'num':{N: '2'}
    }
};
dynamodb.deleteItem(params, function(err, data) {
    if(err) {
        console.log(err, err.stack);
    } else {
        console.log(data);
    }
});

⦿ テーブル削除

ひと通り確認が終わったのでテーブルを削除する。

$ aws dynamodb delete-table --table-name test \
--endpoint-url http://localhost:8000
{
    "TableDescription": {
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/test", 
        "AttributeDefinitions": [
            {
                "AttributeName": "num", 
                "AttributeType": "N"
            }
        ], 
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0, 
            "WriteCapacityUnits": 1, 
            "LastIncreaseDateTime": 0.0, 
            "ReadCapacityUnits": 1, 
            "LastDecreaseDateTime": 0.0
        }, 
        "TableSizeBytes": 14, 
        "TableName": "test", 
        "BillingModeSummary": {
            "LastUpdateToPayPerRequestDateTime": 0.0, 
            "BillingMode": "PROVISIONED"
        }, 
        "TableStatus": "ACTIVE", 
        "KeySchema": [
            {
                "KeyType": "HASH", 
                "AttributeName": "num"
            }
        ], 
        "ItemCount": 1, 
        "CreationDateTime": 1571411233.367
    }
}

AWS CLIやJavaScriptを使って他にも様々な操作ができるので以下のドキュメントを参照のこと。

DynamoDBローカルのバックエンドはSQLite

DynamoDBローカルのバックエンドはSQLiteを使っているのでSQLiteの各種ツールで中身を参照することができる。

ファイルはDynamoDBローカルのサーバを起動したカレントディレクトリに「shared-local-instance.db」として作成される。

ファイルは一つだけなのでバックアップや別ホストへのコピーも容易に行える。

$ sqlite3 shared-local-instance.db 
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.

sqlite> .tables
cf    dm    sm    ss    test  tr    us 

テーブルはそれぞれ以下の用途に使われている。

⦿ cf
DynamoDBローカルのバージョン

sqlite> .schema cf
CREATE TABLE cf (version TEXT);

sqlite> select * from cf;
v2.4.0

⦿ dm
DynamoDBローカル内に定義したテーブルの情報

sqlite> .schema dm
CREATE TABLE dm (TableName TEXT, CreationDateTime INTEGER, LastDecreaseDate INTEGER, LastIncreaseDate INTEGER, NumberOfDecreasesToday INTEGER, ReadCapacityUnits INTEGER, WriteCapacityUnits INTEGER, TableInfo BLOB, BillingMode INTEGER DEFAULT 0, PayPerRequestDateTime INTEGER DEFAULT 0, PRIMARY KEY(TableName));

sqlite> select * from dm;
test|1571441645458|0|0|0|1|1|{"Attributes":[{"AttributeName":"num","AttributeType":"N"}],"GSIList":[],"GSIDescList":[],"SQLiteIndex":{"":[{"DynamoDBAttribute":{"AttributeName":"num","AttributeType":"N"},"KeyType":"HASH","SQLiteColumnName":"hashKey","SQLiteDataType":"BLOB"}]},"UniqueIndexes":[{"DynamoDBAttribute":{"AttributeName":"num","AttributeType":"N"},"KeyType":"HASH","SQLiteColumnName":"hashKey","SQLiteDataType":"BLOB"}],"UniqueGSIIndexes":[]}|0|0

⦿ sm / ss / us
DynamoDB Stream管理情報

sqlite> .schema sm
CREATE TABLE sm (StreamID TEXT, StreamStatus TEXT, TableName TEXT, StreamInfo BLOB, CreationDateTime INTEGER, DeletionDateTime INTEGER, PRIMARY KEY(StreamID));

sqlite> .schema ss
CREATE TABLE ss (StreamID TEXT, ShardID TEXT, CreationDateTime INTEGER, DeletionDateTime INTEGER, InitialSequenceNumberStart INTEGER, SequenceNumberEnd INTEGER, ParentShardID TEXT, PRIMARY KEY(ShardID));

sqlite> .schema us
CREATE TABLE us (StreamID TEXT, ShardID TEXT, SequenceNumber INTEGER, CreationDateTime INTEGER, StreamRecord BLOB, OperationType TEXT, PRIMARY KEY(SequenceNumber));

sqlite> select * from sm;

sqlite> select * from ss;

sqlite> select * from us;

⦿ test
今回の導入手順でテスト用に作成したテーブル

sqlite> .schema test
CREATE TABLE IF NOT EXISTS "test" (hashKey BLOB DEFAULT NULL, hashValue BLOB NOT NULL, itemSize INTEGER DEFAULT 0, ObjectJSON BLOB NOT NULL, PRIMARY KEY(hashKey));
CREATE INDEX "test*HVI" ON "test" (hashValue);

sqlite> select * from test;
>=E10000000000000000000000000000000000000|-��,q���� �T  �����|14|{"data":{"S":"first"},"num":{"N":"1"}}

⦿ tr
トランザクション管理情報

sqlite> .schema tr
CREATE TABLE tr (TransactionId TEXT, TransactionSignature BLOB, CreationDateTime INTEGER, PRIMARY KEY(TransactionId));

sqlite> select * from tr;

参考サイト

元記事はこちら

[Amazon Web Services] DynamoDBローカル導入手順