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();
ちなみにこれだとグローバルセカンダリインデクスやローカルセカンダリインデクスに対応していないなど、いくつも問題がありますが、一般的なテーブルの用途としてはなんとか使えるかな、とは思います。
まとめ
何かいい方法があればぜひ教えてください。