it-swarm.com.ru

Удаление из Amazon Dynamodb

Есть ли эффективный способ удалить все элементы из таблицы Amazon Dynamodb одновременно. Я просмотрел документы aws, но там показано удаление одного элемента.

19
rampuriyaaa

Вы захотите использовать BatchWriteItem , если вы не можете удалить таблицу. Если все ваши записи находятся в одном HashKey, вы можете использовать API Query для извлечения записей, а затем удалять их по 25 элементов за раз. Если нет, вам, вероятно, придется сканировать.

В качестве альтернативы, вы можете предоставить простую обертку вокруг AmazonDynamoDBClient (из официального SDK), которая собирает набор ключей Hash/Range, существующих в вашей таблице. Тогда вам не нужно будет запрашивать или сканировать элементы, вставленные после теста, поскольку у вас уже есть встроенный набор. Это будет выглядеть примерно так:

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 - это класс в DynamoDB SDK , который принимает ноль, один или два объекта AttributeValue в конструкторе для представления ключа хеша или ключа хеша/диапазона. Предполагая, что методы equals и hashCode работают, вы можете использовать их в описанных мною Set. Если нет, вам придется написать свой собственный класс Key.

Это должно получить вам поддерживаемый набор для использования в ваших тестах. Это не относится к таблице, поэтому вам может понадобиться добавить еще один слой коллекции, если вы используете несколько таблиц. Это изменит Set<Key> на что-то вроде Map<TableName, Set<Key>>. Вам нужно будет посмотреть на свойство getTableName(), чтобы выбрать правильный Set для обновления.

Как только ваш тест закончится, захват содержимого таблицы и удаление должны быть простыми.

Одно последнее предложение: используйте для тестирования другую таблицу, чем для своего приложения. Создайте идентичную схему, но дайте таблице другое имя. Возможно, вы даже хотите, чтобы другой пользователь IAM не позволил вашему тестовому коду получить доступ к вашей рабочей таблице. Если у вас есть вопросы по этому поводу, не стесняйтесь открыть отдельный вопрос для этого сценария.

3
Steven Hood

Сделайте следующие шаги: 

  1. Сделать запрос на удаление таблицы
  2. В ответ вы получите описание стола
  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 ()): ( учетные данные нужно установить.)

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

Как говорит Ихтшем, самый эффективный способ - удалить и заново создать таблицу. Однако, если это нецелесообразно (например, из-за сложной конфигурации таблицы, такой как лямбда-триггеры), вот некоторые команды CLI AWS для удаления всех записей. Им требуется программа jq для обработки JSON.

Удаление записей по одной (медленно!), При условии, что ваша таблица называется my_table, ваш ключ раздела называется partition_key, а ключ сортировки (если есть) называется 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

Удаление записей партиями до 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, ваша емкость записи была превышена. Вы можете объяснить это, уменьшив размер партии. Для меня каждая партия занимает около секунды, поэтому при скорости записи 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

Вы можете воссоздать таблицу DynamoDB, используя 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