web-dev-qa-db-ja.com

Amazon dynamodbからの削除

Amazon dynamodbテーブルからすべてのアイテムを一度に削除する効率的な方法はありますか?awsドキュメントを確認しましたが、1つのアイテムの削除が表示されています。

20
rampuriyaaa

テーブルをドロップできない場合は、 BatchWriteItem を使用します。すべてのエントリが単一のHashKey内にある場合、クエリAPIを使用してレコードを取得し、一度に25項目を削除できます。そうでない場合は、おそらくスキャンする必要があります。

または、テーブルに存在するハッシュ/範囲キーのセットを収集するAmazonDynamoDBClientのシンプルなラッパー(公式SDKから)を提供することもできます。そうすれば、すでにセットが作成されているので、テスト後に挿入したアイテムをクエリしたりスキャンしたりする必要はありません。これは次のようになります。

_public class KeyCollectingAmazonDynamoDB implements AmazonDynamoDB
{
    private final AmazonDynamoDB delegate;
    // HashRangePair is something you have to define
    private final Set<Key> contents;

    public InsertGatheringAmazonDynamoDB( AmazonDynamoDB delegate )
    {
        this.delegate = delegate;
        this.contents = new HashSet<>();
    }

    @Override
    public PutItemResult putItem( PutItemRequest putItemRequest )
            throws AmazonServiceException, AmazonClientException
    {
        contents.add( extractKey( putItemRequest.getItem() ) );
        return delegate.putItem( putItemRequest );
    }

    private Key extractKey( Map<String, AttributeValue> item )
    {
        // TODO Define your hash/range key extraction here
        // Create a Key object
        return new Key( hashKey, rangeKey );
    }

    @Override
    public DeleteItemResult deleteItem( DeleteItemRequest deleteItemRequest )
            throws AmazonServiceException, AmazonClientException
    {
        contents.remove( deleteItemRequest.getKey() );
        return delegate.deleteItem( deleteItemRequest );
    }

    @Override
    public BatchWriteItemResult batchWriteItem( BatchWriteItemRequest batchWriteItemRequest )
            throws AmazonServiceException, AmazonClientException
    {
        // Similar extraction, but in bulk.
        for ( Map.Entry<String, List<WriteRequest>> entry : batchWriteItemRequest.getRequestItems().entrySet() )
        {
            String tableName = entry.getKey();
            List<WriteRequest> writeRequests = entry.getValue();
            for ( WriteRequest writeRequest : writeRequests )
            {
                PutRequest putRequest = writeRequest.getPutRequest();
                if ( putRequest != null )
                {
                    // Add to Set just like putItem
                }
                DeleteRequest deleteRequest = writeRequest.getDeleteRequest();
                if ( deleteRequest != null )
                {
                    // Remove from Set just like deleteItem
                }
            }
        }

        // Write through to DynamoDB
        return delegate.batchWriteItem( batchWriteItemRequest );
    }

    // remaining methods elided, since they're direct delegation
}
_

KeyDynamoDB SDK 内のクラスで、コンストラクターで0、1、または2つのAttributeValueオブジェクトを受け入れ、ハッシュキーまたはハッシュ/範囲キーを表します。 equalsメソッドとhashCodeメソッドが機能する場合、私が説明したSet内で使用できます。そうでない場合は、独自のKeyクラスを作成する必要があります。

これにより、テストで使用するための保守されたセットが得られます。これはテーブルに固有のものではないため、複数のテーブルを使用している場合は、コレクションの別のレイヤーを追加する必要がある場合があります。これは_Set<Key>_を_Map<TableName, Set<Key>>_のようなものに変更します。更新する正しいSetを選択するには、getTableName()プロパティを確認する必要があります。

テストが終了したら、テーブルの内容を取得して削除するのは簡単です。

最後に、アプリケーションのテストとは異なるテーブルをテストに使用することをお勧めします。同一のスキーマを作成しますが、テーブルに別の名前を付けます。おそらく、別のIAMユーザーがテストコードから実稼働テーブルにアクセスできないようにすることもできます。それについて質問がある場合は、そのシナリオについて別の質問を自由に開いてください。

4
Steven Hood

次の手順を実行します。

  1. テーブルの削除リクエストを行う
  2. 応答では、TableDescriptionを取得します
  3. TableDescriptionを使用して、テーブルを再度作成します。

ステップ1および2については、ここをクリックしてください

ステップ3はここをクリック

それが私のアプリケーションで行うことです。

13
Ihtsham Minhas

DynamoDBMapperは、数行で処理を実行します。

AWSCredentials credentials = new PropertiesCredentials(credentialFile);
client = new AmazonDynamoDBClient(credentials);
DynamoDBMapper mapper = new DynamoDBMapper(this.client);
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
PaginatedScanList<LogData> result = mapper.scan(LogData.class,  scanExpression);
for (LogData data : result) {
    mapper.delete(data);
}
5
Nicolas M

参考までに、Python 3でアイテムごとに削除する簡単なソリューション( Boto3 を使用)および scan()):( Credentials を設定する必要があります。)

def delete_all_items(table_name):
    # Deletes all items from a DynamoDB table.
    # You need to confirm your intention by pressing Enter.
    import boto3
    client = boto3.client('dynamodb')
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table(table_name)
    response = client.describe_table(TableName=table_name)
    keys = [k['AttributeName'] for k in response['Table']['KeySchema']]
    response = table.scan()
    items = response['Items']
    number_of_items = len(items)
    if number_of_items == 0:  # no items to delete
        print("Table '{}' is empty.".format(table_name))
        return
    print("You are about to delete all ({}) items from table '{}'."
          .format(number_of_items, table_name))
    input("Press Enter to continue...")
    with table.batch_writer() as batch:
        for item in items:
            key_dict = {k: item[k] for k in keys}
            print("Deleting " + str(item) + "...")
            batch.delete_item(Key=key_dict)

delete_all_items("test_table")

明らかに、これはたくさんのアイテムを持つテーブルには使用しないでください。 (100+)そのため、削除/再作成のアプローチはより安価で効率的です。

5
Attila Tanyi

Ihtshamが言うように、最も効率的な方法は、テーブルを削除して再作成することです。ただし、それが実用的でない場合(たとえば、Lambdaトリガーなどのテーブルの複雑な構成が原因で)、すべてのレコードを削除するAWS CLIコマンドを次に示します。 JSON処理には jq プログラムが必要です。

テーブルをmy_tableと呼び、パーティションキーをpartition_keyと呼び、ソートキー(存在する場合)をsort_keyと呼ぶと仮定して、レコードを1つずつ削除します(遅い!):

aws dynamodb scan --table-name my_table | \
  jq -c '.Items[] | { partition_key, sort_key }' | \
  tr '\n' '\0' | \
  xargs -0 -n1 -t aws dynamodb delete-item --table-name my_table --key

最大25レコードのバッチでのレコードの削除:

aws dynamodb scan --table-name my_table | \
  jq -c '[.Items | keys[] as $i | { index: $i, value: .[$i]}] | group_by(.index / 25 | floor)[] | { "my_table": [.[].value | { "DeleteRequest": { "Key": { partition_key, sort_key }}}] }' | \
  tr '\n' '\0' | \
  xargs -0 -n1 -t aws dynamodb batch-write-item --request-items

空でないUnprocessedItems応答が表示される場合は、書き込み容量を超えています。バッチサイズを減らすことで、これを考慮することができます。私の場合、各バッチの送信には約1秒かかるため、1秒あたり5の書き込み容量で、バッチサイズを5に設定しました。

4
Trevor Robinson

私はそれを行うために次のJavaScriptコードを使用します。

async function truncate(table, keys) {

    const limit = (await db.describeTable({
        TableName: table
    }).promise()).Table.ProvisionedThroughput.ReadCapacityUnits;

    let total = 0;
    let lastEvaluatedKey = null;
    do {
        const qp = {
            TableName: table,
            Limit: limit,
            ExclusiveStartKey: lastEvaluatedKey,
            ProjectionExpression: keys.join(' '),
        };

        const qr = await ddb.scan(qp).promise();

        lastEvaluatedKey = qr.LastEvaluatedKey;

        const dp = {
            RequestItems: {
            },
        };

        dp.RequestItems[table] = [];

        if (qr.Items) {
            for (const i of qr.Items) {
                const dr = {
                    DeleteRequest: {
                        Key: {
                        }
                    }
                };

                keys.forEach(k => {
                    dr.DeleteRequest.Key[k] = i[k];
                });

                dp.RequestItems[table].Push(dr);

                if (dp.RequestItems[table].length % 25 == 0) {
                    await ddb.batchWrite(dp).promise();
                    total += dp.RequestItems[table].length;
                    dp.RequestItems[table] = [];
                }
            }
            if (dp.RequestItems[table].length > 0) {
                await ddb.batchWrite(dp).promise();
                total += dp.RequestItems[table].length;
                dp.RequestItems[table] = [];
            }
        }

        console.log(`Deleted ${total}`);

        setTimeout(() => {}, 1000);

    } while (lastEvaluatedKey);
}

(async () => {
    truncate('table_name', ['id']);
})();
0
Mike Shauneu

この場合、テーブルを削除して新しいテーブルを作成できます。

例:

from __future__ import print_function # Python 2/3 compatibility
import boto3

dynamodb = boto3.resource('dynamodb', region_name='us-west-2', endpoint_url="http://localhost:8000")

table = dynamodb.Table('Movies')

table.delete()
0

AWS Java SDKを使用してDynamoDBテーブルを再作成できます

// Init DynamoDB client
AmazonDynamoDB dynamoDB = AmazonDynamoDBClientBuilder.standard().build();

// Get table definition
TableDescription tableDescription = dynamoDB.describeTable("my-table").getTable();

// Delete table
dynamoDB.deleteTable("my-table");

// Create table
CreateTableRequest createTableRequest = new CreateTableRequest()
        .withTableName(tableDescription.getTableName())
        .withAttributeDefinitions(tableDescription.getAttributeDefinitions())
        .withProvisionedThroughput(new ProvisionedThroughput()
                .withReadCapacityUnits(tableDescription.getProvisionedThroughput().getReadCapacityUnits())
                .withWriteCapacityUnits(tableDescription.getProvisionedThroughput().getWriteCapacityUnits())
        )
        .withKeySchema(tableDescription.getKeySchema());

dynamoDB.createTable(createTableRequest);
0
Rafal Enden