web-dev-qa-db-fra.com

Suppression d'Amazon Dynamodb

Existe-t-il un moyen efficace de supprimer tous les éléments d'une table Amazon dynamodb à la fois. J'ai parcouru la documentation aws, mais la suppression d'un seul élément est indiquée.

19
rampuriyaaa

Vous voudrez utiliser BatchWriteItem si vous ne pouvez pas supprimer la table. Si toutes vos entrées se trouvent dans une même HashKey, vous pouvez utiliser l'API de requête pour extraire les enregistrements, puis les supprimer à raison de 25 éléments à la fois. Sinon, vous devrez probablement scanner.

Vous pouvez également fournir un simple wrapper autour de AmazonDynamoDBClient (à partir du SDK officiel) qui collecte un ensemble de clés de hachage/plage existant dans votre table. Dans ce cas, vous n'avez pas besoin d'interroger ou de rechercher les éléments que vous avez insérés après le test, car l'ensemble est déjà créé. Cela ressemblerait à ceci:

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
}

Key est une classe du DynamoDB SDK qui accepte zéro, un ou deux objets AttributeValue dans le constructeur pour représenter une clé de hachage ou une clé de hachage/plage. En supposant que les méthodes equals et hashCode fonctionnent, vous pouvez les utiliser dans la Set que j'ai décrite. Si ce n'est pas le cas, vous devrez écrire votre propre classe Key.

Cela devrait vous fournir un ensemble maintenu pour une utilisation dans vos tests. Ce n'est pas spécifique à une table, vous devrez donc peut-être ajouter une autre couche de collection si vous utilisez plusieurs tables. Cela changerait Set<Key> en quelque chose comme Map<TableName, Set<Key>>. Il vous faudrait examiner la propriété getTableName() pour sélectionner la Set correcte à mettre à jour.

Une fois votre test terminé, récupérer le contenu de la table et le supprimer devrait être simple.

Une dernière suggestion: utilisez pour le test une table différente de celle utilisée pour votre application. Créez un schéma identique, mais attribuez un nom différent à la table. Vous voudrez probablement qu'un autre utilisateur IAM empêche votre code de test d'accéder à votre table de production. Si vous avez des questions à ce sujet, n'hésitez pas à ouvrir une question distincte pour ce scénario.

3
Steven Hood

Effectuez les étapes suivantes: 

  1. Faire une demande de suppression de table
  2. Dans la réponse, vous obtiendrez la TableDescription
  3. En utilisant TableDescription, créez à nouveau la table.

Pour les étapes 1 et 2, cliquez ici

pour l'étape 3 cliquez ici

C'est ce que je fais dans ma candidature.

13
Ihtsham Minhas

DynamoDBMapper fera le travail en quelques lignes:

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

Juste pour mémoire, une solution rapide avec suppression élément par élément dans Python 3 (utilisant Boto3 et scan ()): ( Informations d'identification besoin d'être réglé.)

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")

Évidemment, cela ne devrait pas être utilisé pour les tables avec beaucoup d’éléments. (100+) Pour cela, l'approche supprimer/recréer est moins chère et plus efficace.

5
Attila Tanyi

Comme le dit ihtsham, le moyen le plus efficace est de supprimer et de recréer la table. Toutefois, si cela n’est pas pratique (en raison, par exemple, de la configuration complexe de la table, telle que des déclencheurs Lambda), voici quelques commandes AWS CLI permettant de supprimer tous les enregistrements. Ils ont besoin du programme jq pour le traitement JSON.

Suppression d'enregistrements un par un (lente!), En supposant que votre table s'appelle my_table, votre clé de partition s'appelle partition_key et votre clé de tri (le cas échéant) s'appelle sort_key:

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

Suppression d'enregistrements par lots de 25 enregistrements maximum:

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

Si vous commencez à voir des réponses UnprocessedItems non vides, votre capacité d'écriture a été dépassée. Vous pouvez en tenir compte en réduisant la taille du lot. Pour moi, chaque lot prend environ une seconde à soumettre. Ainsi, avec une capacité d'écriture de 5 par seconde, je règle la taille du lot à 5.

4
Trevor Robinson

J'utilise le code javascript suivant pour le faire:

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

Vous pouvez recréer une table DynamoDB à l'aide d'AWS Java SDK.

// 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