Local DynamoDBのテーブルデータを削除したいときの実装(テーブル削除→作成)

Local DynamoDBのテーブルを残したまま中身を削除したくなったので、その時のメモ。Amazon DynamoDBを使っていれば、コンソールから消せますが、ローカルのDynamoDBを使っていると、なかなか面倒ですよね。

前提1:DynamoDBには複数データ削除用のメソッドはない

テーブルの削除(deleteTable)、データを1件削除(deleteItem)はありますが、テーブル定義を残しつつデータのみを削除するメソッドは用意されていません。(DynamoDBの特性を考えればわからんでもないですが)

前提2:Scanした結果のItemはdeleteItemメソッドでは使えない

ではとりあえずScanした結果を使ってItemを取り出して1個ずつ消そうかとこんなコードを組んでみますが

for (Map<String, AttributeValue> item : scanResult.getItems()) {
  DeleteItemRequest request = new DeleteItemRequest().withTableName(tableName).withKey(item);
  this.dynamoDB.deleteItem(request);
}

エラーが出力され、削除できません。deleteItemメソッドが受け付けるItemの内容は、getItemで取得したデータとマッチするようです。

com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: The number of conditions on the keys is invalid (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1586) ~[aws-java-sdk-core-1.11.75.jar:na]
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1254) ~[aws-java-sdk-core-1.11.75.jar:na]
    at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1035) ~[aws-java-sdk-core-1.11.75.jar:na]

一度テーブルを削除して同じ名前で複製。

結局はこの方法をとりました。Queryで1件1件取得しては削除して、、、とも考えたのですが、こちらの方が楽かな、、、と。

で、以下がコードになります。まだ削除後のテーブルを復旧しきれていないものもあるので、これから足りない分は補足します。

DescribeTableRequest describeRequest = new DescribeTableRequest().withTableName(tableName);
DescribeTableResult describeResult = this.dynamoDB.describeTable(describeRequest);
CreateTableRequest createRequest = new CreateTableRequest().withTableName(tableName)
        .withAttributeDefinitions(describeResult.getTable().getAttributeDefinitions())
        .withKeySchema(describeResult.getTable().getKeySchema())
        .withProvisionedThroughput(new ProvisionedThroughput()
                .withReadCapacityUnits(describeResult.getTable().getProvisionedThroughput().getReadCapacityUnits())
                .withWriteCapacityUnits(describeResult.getTable().getProvisionedThroughput().getWriteCapacityUnits()));

DynamoDB db = new DynamoDB(this.dynamoDB);
Table table = db.getTable(tableName);
table.delete();
table.waitForDelete();

table = db.createTable(createRequest);
table.waitForActive();

ちなみにこれだとグローバルセカンダリインデクスやローカルセカンダリインデクスに対応していないなど、いくつも問題がありますが、一般的なテーブルの用途としてはなんとか使えるかな、とは思います。

スクリーンショット 2017-04-17 8.45.17.png

まとめ

何かいい方法があればぜひ教えてください。