Trabalhar com itens e atributos - Amazon DynamoDB

Trabalhar com itens e atributos

No Amazon DynamoDB, um item é uma coleção de atributos. Cada atributo tem um nome e um valor. Um valor de atributo pode ser uma escalar, um conjunto ou um tipo de documento. Para ter mais informações, consulte Amazon DynamoDB: como funciona.

O DynamoDB fornece quatro operações para a funcionalidade básica criar, ler, atualizar e excluir (CRUD). Todas essas operações são atômicas.

  • PutItem: criar um item.

  • GetItem: ler um item.

  • UpdateItem: atualizar um item.

  • DeleteItem: excluir um item.

Cada uma dessas operações exige que você especifique a chave primária do item com o qual deseja trabalhar. Por exemplo, para ler um item usando GetItem, você deve especificar a chave de partição e a chave de classificação (se aplicável) desse item.

Além das quatro operações CRUD básicas, o DynamoDB também fornece o seguinte:

  • BatchGetItem: ler até 100 itens de uma ou mais tabelas.

  • BatchWriteItem: criar ou excluir até 25 itens em uma ou mais tabelas.

Essas operações em lote combinam várias operações CRUD em uma única solicitação. Além disso, as operações em lote leem e gravam itens em paralelo para reduzir as latências de resposta.

Esta seção descreve como usar essas operações e inclui tópicos relacionados, como contadores atômicos e atualizações condicionais. Esta seção também inclui código de exemplo que usa os AWS SDKs.

Ler um item

Para ler um item de uma tabela do DynamoDB use a operação GetItem. Você deve fornecer o nome da tabela, juntamente com a chave primária do item desejado.

exemplo

O exemplo da AWS CLI a seguir mostra como ler um item da tabela ProductCatalog.

aws dynamodb get-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}'
nota

Com GetItem, você deve especificar a chave primária inteira, não apenas parte dela. Por exemplo, se uma tabela tiver uma chave primária composta (chave de partição e chave de classificação), você deverá fornecer um valor para a chave de partição e um valor para a chave de classificação.

A solicitação GetItem executa uma leitura final consistente, por padrão. Você pode usar o parâmetro ConsistentRead para solicitar uma leitura altamente consistente. (Isso consome unidades de capacidade de leitura adicionais, mas retorna a versão mais recente do item.)

GetItem retornará todos os atributos do item. Você pode usar uma expressão de projeção para retornar apenas alguns dos atributos. Para ter mais informações, consulte Expressões de projeção.

Para retornar o número de unidades de capacidade de leitura consumidas por GetItem, defina o parâmetro ReturnConsumedCapacity como TOTAL.

exemplo

O exemplo da AWS Command Line Interface (AWS CLI) a seguir mostra alguns dos parâmetros opcionais de GetItem.

aws dynamodb get-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}' \ --consistent-read \ --projection-expression "Description, Price, RelatedItems" \ --return-consumed-capacity TOTAL

Gravar um item

Para criar, atualizar ou excluir um item em uma tabela do DynamoDB use uma das seguintes operações:

  • PutItem

  • UpdateItem

  • DeleteItem

Para cada uma dessas operações, você deve especificar a chave primária inteira, não apenas parte dela. Por exemplo, se uma tabela tiver uma chave primária composta (chave de partição e chave de classificação), você deve fornecer um valor para a chave de partição e um valor para a chave de classificação.

Para retornar o número de unidades de capacidade de gravação consumidas por qualquer uma dessas operações, defina o parâmetro ReturnConsumedCapacity de uma das seguintes formas:

  • TOTAL: retorna o número total de unidades de capacidade de gravação consumidas.

  • INDEXES: retorna o número total de unidades de capacidade de gravação consumidas, com subtotais para a tabela e para todos os índices secundários que foram afetados pela operação.

  • NONE: nenhum detalhe da capacidade de gravação é retornado. (Esse é o padrão.)

PutItem

PutItem cria um novo item. Se um item com a mesma chave já existir na tabela, ele será substituído pelo novo item.

exemplo

Gravar um novo item na tabela Thread. A chave primária de Thread consiste em ForumName (chave de partição) e Subject (chave de classificação).

aws dynamodb put-item \ --table-name Thread \ --item file://item.json

Os argumentos de --item são armazenados no arquivo item.json.

{ "ForumName": {"S": "Amazon DynamoDB"}, "Subject": {"S": "New discussion thread"}, "Message": {"S": "First post in this thread"}, "LastPostedBy": {"S": "fred@example.com"}, "LastPostDateTime": {"S": "201603190422"} }

UpdateItem

Se um item com a chave especificada não existir, UpdateItem criará um item. Caso contrário, ele modificará os atributos de um item existente.

Você usa uma expressão de atualização para especificar os atributos que deseja modificar e seus novos valores. Para ter mais informações, consulte Expressões de atualização.

Na expressão de atualização, use valores de atributos de expressão como espaços reservados para os valores reais. Para ter mais informações, consulte Valores de atributo de expressão.

exemplo

Modifique vários atributos no item Thread. O parâmetro opcional ReturnValues mostra o item como ele aparece após a atualização. Para ter mais informações, consulte Retornar valores.

aws dynamodb update-item \ --table-name Thread \ --key file://key.json \ --update-expression "SET Answered = :zero, Replies = :zero, LastPostedBy = :lastpostedby" \ --expression-attribute-values file://expression-attribute-values.json \ --return-values ALL_NEW

Os argumentos de --key são armazenados no arquivo key.json.

{ "ForumName": {"S": "Amazon DynamoDB"}, "Subject": {"S": "New discussion thread"} }

Os argumentos de --expression-attribute-values são armazenados no arquivo expression-attribute-values.json.

{ ":zero": {"N":"0"}, ":lastpostedby": {"S":"barney@example.com"} }

DeleteItem

DeleteItem exclui o item com a chave especificada.

exemplo

O exemplo da AWS CLI a seguir mostra como excluir o item Thread.

aws dynamodb delete-item \ --table-name Thread \ --key file://key.json

Retornar valores

Em alguns casos, talvez você queira que o DynamoDB retorne determinados valores de atributos como eles apareciam antes ou depois de modificados. As operações PutItem, UpdateItem e DeleteItem têm um parâmetro ReturnValues que você pode usar para retornar os valores de atributo antes ou depois que eles sejam modificados.

O valor padrão de ReturnValues é NONE, o que significa que o DynamoDB não retornará nenhuma informação sobre os atributos que foram modificados.

Veja a seguir as outras configurações válidas de ReturnValues, organizadas pela operação da API do DynamoDB.

PutItem

  • ReturnValues: ALL_OLD

    • Se você substituir um item existente, ALL_OLD retornará o item inteiro, conforme ele aparecia antes da substituição.

    • Se você gravar um item que não existe, ALL_OLD não terá efeito.

UpdateItem

O uso mais comum de UpdateItem é para atualizar um item existente. No entanto, UpdateItem realmente executa um upsert, o que significa que ele criará o item automaticamente se ele ainda não existir.

  • ReturnValues: ALL_OLD

    • Se você atualizar um item existente, ALL_OLD retornará o item inteiro, conforme ele aparecia antes da atualização.

    • Se você atualizar um item que não existe (upsert), ALL_OLD não terá efeito.

  • ReturnValues: ALL_NEW

    • Se você atualizar um item existente, ALL_NEW retornará o item inteiro, conforme ele aparecia depois da atualização.

    • Se você atualizar um item que não existe (upsert), ALL_NEW retornará o item inteiro.

  • ReturnValues: UPDATED_OLD

    • Se você atualizar um item existente, UPDATED_OLD retornará apenas os atributos atualizados, como eles apareciam antes da atualização.

    • Se você atualizar um item que não existe (upsert), UPDATED_OLD não terá efeito.

  • ReturnValues: UPDATED_NEW

    • Se você atualizar um item existente, UPDATED_NEW retornará apenas os atributos afetados, como eles apareciam depois da atualização.

    • Se você atualizar um item que não existe (upsert), UPDATED_NEW retornará apenas os atributos atualizados, conforme eles aparecem após a atualização.

DeleteItem

  • ReturnValues: ALL_OLD

    • Se você excluir um item existente, ALL_OLD retornará o item inteiro, como ele aparecia antes de você excluí-lo.

    • Se você excluir um item que não existe, ALL_OLD não retornará nenhum dado.

Operações em lote

Para aplicações que precisam ler ou gravar vários itens, o DynamoDB fornece as operações BatchGetItem e BatchWriteItem. Usar essas operações pode reduzir o número de round trips da rede da sua aplicação para o DynamoDB. Além disso, o DynamoDB executa as operações de leitura ou gravação individuais em paralelo. Suas aplicações se beneficiam desse paralelismo sem a necessidade de gerenciar a simultaneidade ou threading.

As operações em lote são essencialmente wrappers em torno de várias solicitações de leitura ou de gravação. Por exemplo, se uma solicitação BatchGetItem contiver cinco itens, o DynamoDB executará cinco operações GetItem em seu nome. Da mesma forma, se uma solicitação BatchWriteItem contiver duas solicitações Put e quatro solicitações Delete, o DynamoDB realizará duas solicitações PutItem e quatro DeleteItem.

Em geral, não há falha em uma operação em lote, a menos que haja falha em todas as solicitações no lote. Por exemplo, suponha que você execute uma operação BatchGetItem, mas que haja falha em uma das solicitações GetItem individuais no lote. Nesse caso, BatchGetItem retorna as chaves e os dados da solicitação GetItem com falha. As outras solicitações GetItem no lote não são afetadas.

BatchGetItem

Uma única operação BatchGetItem pode conter até 100 solicitações GetItem individuais e recuperar até 16 MB de dados. Além disso, uma operação BatchGetItem pode recuperar itens de várias tabelas.

exemplo

Recuperar dois itens da tabela Thread usando uma expressão de projeção para retornar apenas alguns dos atributos.

aws dynamodb batch-get-item \ --request-items file://request-items.json

Os argumentos de --request-items são armazenados no arquivo request-items.json.

{ "Thread": { "Keys": [ { "ForumName":{"S": "Amazon DynamoDB"}, "Subject":{"S": "DynamoDB Thread 1"} }, { "ForumName":{"S": "Amazon S3"}, "Subject":{"S": "S3 Thread 1"} } ], "ProjectionExpression":"ForumName, Subject, LastPostedDateTime, Replies" } }

BatchWriteItem

A operação BatchWriteItem pode conter até 25 solicitações PutItem e DeleteItem individuais e gravar até 16 MB de dados. (O tamanho máximo de um item individual é 400 KB.) Além disso, uma operação BatchWriteItem pode inserir ou excluir itens em várias tabelas.

nota

BatchWriteItem não é compatível com solicitações UpdateItem.

exemplo

Gravar dois itens na tabela ProductCatalog.

aws dynamodb batch-write-item \ --request-items file://request-items.json

Os argumentos de --request-items são armazenados no arquivo request-items.json.

{ "ProductCatalog": [ { "PutRequest": { "Item": { "Id": { "N": "601" }, "Description": { "S": "Snowboard" }, "QuantityOnHand": { "N": "5" }, "Price": { "N": "100" } } } }, { "PutRequest": { "Item": { "Id": { "N": "602" }, "Description": { "S": "Snow shovel" } } } } ] }

Contadores atômicos

Você pode usar a operação UpdateItem para implementar um contador atômico, um atributo numérico que é incrementado incondicionalmente sem interferir em outras solicitações de gravação. (Todas as solicitações de gravação são aplicadas na ordem em que foram recebidas.) Com um contador atômico, as atualizações não são imutáveis. Em outras palavras, o valor numérico é incrementado ou reduzido cada vez que você chama UpdateItem. Se o valor de incremento usado para atualizar o contador atômico for positivo, isso poderá causar contagem a mais. Se o valor do incremento for negativo, isso poderá causar contagem a menos.

Você pode usar um contador atômico para rastrear o número de visitantes de um site. Neste caso, sua aplicação poderia incrementar um valor numérico, independentemente do seu valor atual. Se houve falha em uma operação UpdateItem, a aplicação poderá simplesmente tentar a operação novamente. Isso arriscaria atualizar o contador duas vezes, mas provavelmente você poderia tolerar uma pequena contagem a mais ou a menos de visitantes do site.

Um contador atômico não seria apropriado onde uma contagem a mais ou a menos não pudesse ser tolerada (por exemplo, em uma aplicação bancária). Nesse caso, é mais seguro usar uma atualização condicional em vez de um contador atômico.

Para ter mais informações, consulte Incrementar e reduzir atributos numéricos.

exemplo

O exemplo da AWS CLI a seguir incrementa o Price de um produto em 5. Neste exemplo, sabia-se que o item existia antes da atualização do contador. Como UpdateItem não é idempotente, o Price aumenta cada vez que você executa esse código.

aws dynamodb update-item \ --table-name ProductCatalog \ --key '{"Id": { "N": "601" }}' \ --update-expression "SET Price = Price + :incr" \ --expression-attribute-values '{":incr":{"N":"5"}}' \ --return-values UPDATED_NEW

Gravações condicionais

Por padrão, as operações de gravação do DynamoDB (PutItem, UpdateItem, DeleteItem) são incondicionais: cada operação substitui um item existente que possui a chave primária especificada.

Opcionalmente, o DynamoDB é compatível com gravações condicionais dessas operações. Uma gravação condicional terá êxito somente se os atributos de item atenderem a uma ou mais condições esperadas. Caso contrário, um erro será retornado.

As gravações condicionais comparam suas condições com a versão atualizada mais recentemente do item. Observe que, se o item não existisse anteriormente ou se a operação bem-sucedida mais recente referente a esse item tivesse sido uma exclusão, a gravação condicional não encontraria nenhum item anterior.

Gravações condicionais são úteis em muitas situações. Por exemplo, talvez você queira que uma operação PutItem tenha êxito somente se já não houver um item com a mesma chave primária. Ou você poderia impedir que uma operação UpdateItem modificasse um item, se um de seus atributos tivesse um determinado valor.

As gravações condicionais são úteis nos casos em que vários usuários tentam modificar o mesmo item. Considere o diagrama a seguir, no qual dois usuários (Alice e Bob) estão trabalhando com o mesmo item de uma tabela do DynamoDB.

Os usuários Alice e Bob tentam modificar um item com Id 1, demonstrando a necessidade de gravações condicionais.

Suponha que Alice usa a AWS CLI para atualizar o atributo Price para 8.

aws dynamodb update-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}' \ --update-expression "SET Price = :newval" \ --expression-attribute-values file://expression-attribute-values.json

Os argumentos de --expression-attribute-values são armazenados no arquivo expression-attribute-values.json:

{ ":newval":{"N":"8"} }

Agora, suponha que Bob emita uma solicitação UpdateItem semelhante mais tarde, mas altere o Price para 12. Para Bob, o parâmetro --expression-attribute-values tem a seguinte aparência.

{ ":newval":{"N":"12"} }

A solicitação de Bob é bem-sucedida, mas a atualização anterior de Alice é perdida.

Para solicitar uma condicional PutItem, DeleteItem ou UpdateItem, especifique uma expressão de condição. Uma expressão de condição é uma string que contém nomes de atributos, operadores condicionais e funções internas. A expressão inteira deve ser avaliada como verdadeira. Caso contrário, haverá falha na operação.

Agora, considere o seguinte diagrama que mostra como gravações condicionais impediriam que a atualização de Alice fosse substituída.

Gravação condicional impedindo que a atualização do usuário Bob sobrescreva a alteração da usuária Alice no mesmo item.

Alice primeiro tenta atualizar Price para 8, mas somente se o Price atual for 10.

aws dynamodb update-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}' \ --update-expression "SET Price = :newval" \ --condition-expression "Price = :currval" \ --expression-attribute-values file://expression-attribute-values.json

Os argumentos de --expression-attribute-values são armazenados no arquivo expression-attribute-values.json.

{ ":newval":{"N":"8"}, ":currval":{"N":"10"} }

A atualização de Alice é bem-sucedida porque a condição é avaliada como verdadeira.

Em seguida, Bob tenta atualizar o Price para 12, mas somente se o Price atual for 10. Para Bob, o parâmetro --expression-attribute-values tem a seguinte aparência.

{ ":newval":{"N":"12"}, ":currval":{"N":"10"} }

Como Alice mudou o Price para 8 anteriormente, a expressão de condição é avaliada como falsa, e há falha na atualização de Bob.

Para ter mais informações, consulte Expressões de condição.

Idempotência de gravação condicional

As gravações condicionais podem ser imutáveis se a verificação condicional estiver no mesmo atributo que está sendo atualizado. Isso significa que o DynamoDB realiza uma determinada solicitação de gravação somente se certos valores de atributo no item corresponderem aos valores estimados no momento da solicitação.

Por exemplo, suponha que você emita uma solicitação de UpdateItem para aumentar o Price de um item em 3, mas somente se o Price atual for 20. Depois de enviar a solicitação, mas antes de obter os resultados de volta, ocorre um erro de rede e você não sabe se a solicitação teve êxito. Como essa gravação condicional é imutável, você pode tentar novamente a mesma solicitação de UpdateItem, e o DynamoDB atualizará o item somente se Price for igual a 20 no momento.

Unidades de capacidade consumidas por gravações condicionais

Se uma ConditionExpression for avaliada como false durante uma gravação condicional, o DynamoDB ainda consumirá capacidade de gravação da tabela. A quantidade consumida depende do tamanho do item existente (ou no mínimo 1). Por exemplo, se um item existente tiver 300 kb e o item que você está tentando criar ou atualizar tiver 310 kb, as unidades de capacidade de gravação consumidas serão 300 se a condição falhar e 310 se a condição for bem-sucedida. Se for um item novo (nenhum item existente), as unidades de capacidade de gravação consumidas serão 1 se a condição falhar e 310 se a condição for bem-sucedida.

nota

As operações de gravação consomem apenas unidades de capacidade de gravação. Elas nunca consomem unidades de capacidade de leitura.

Uma gravação condicional com falha retorna uma ConditionalCheckFailedException. Quando isso ocorre, você não recebe nenhuma informação na resposta sobre a capacidade de gravação que foi consumida.

Para retornar o número de unidades de capacidade de gravação consumidas durante uma gravação condicional, você deve usar o parâmetro ReturnConsumedCapacity:

  • TOTAL: retorna o número total de unidades de capacidade de gravação consumidas.

  • INDEXES: retorna o número total de unidades de capacidade de gravação consumidas, com subtotais para a tabela e para todos os índices secundários que foram afetados pela operação.

  • NONE: nenhum detalhe da capacidade de gravação é retornado. (Esse é o padrão.)

nota

Ao contrário de um índice secundário global, um índice secundário local compartilha a capacidade de throughput provisionada com sua tabela. A atividade de leitura e gravação em um índice secundário local consome a capacidade de throughput provisionado da tabela.