DynamoDB - Guia rápido

O DynamoDB permite aos usuários criar bancos de dados capazes de armazenar e recuperar qualquer quantidade de dados e atender a qualquer quantidade de tráfego. Ele distribui automaticamente os dados e o tráfego pelos servidores para gerenciar dinamicamente as solicitações de cada cliente e também mantém um desempenho rápido.

DynamoDB vs. RDBMS

O DynamoDB usa um modelo NoSQL, o que significa que usa um sistema não relacional. A tabela a seguir destaca as diferenças entre DynamoDB e RDBMS -

Tarefas comuns RDBMS DynamoDB
Connect to the Source Ele usa uma conexão persistente e comandos SQL. Ele usa solicitações HTTP e operações de API
Create a Table Suas estruturas fundamentais são tabelas e devem ser definidas. Ele usa apenas chaves primárias e nenhum esquema na criação. Ele usa várias fontes de dados.
Get Table Info Todas as informações da mesa permanecem acessíveis Apenas as chaves primárias são reveladas.
Load Table Data Ele usa linhas feitas de colunas. Nas tabelas, ele usa itens feitos de atributos
Read Table Data Ele usa instruções SELECT e instruções de filtragem. Ele usa GetItem, Query e Scan.
Manage Indexes Ele usa índices padrão criados por meio de instruções SQL. As modificações ocorrem automaticamente nas mudanças da tabela. Ele usa um índice secundário para atingir a mesma função. Requer especificações (chave de partição e chave de classificação).
Modify Table Data Ele usa uma instrução UPDATE. Ele usa uma operação UpdateItem.
Delete Table Data Ele usa uma instrução DELETE. Ele usa uma operação DeleteItem.
Delete a Table Ele usa uma instrução DROP TABLE. Ele usa uma operação DeleteTable.

Vantagens

As duas principais vantagens do DynamoDB são escalabilidade e flexibilidade. Ele não força o uso de uma determinada fonte de dados e estrutura, permitindo aos usuários trabalhar com praticamente qualquer coisa, mas de forma uniforme.

Seu design também suporta uma ampla gama de uso, desde tarefas e operações mais leves até funcionalidades empresariais exigentes. Também permite o uso simples de várias linguagens: Ruby, Java, Python, C #, Erlang, PHP e Perl.

Limitações

O DynamoDB sofre de certas limitações, no entanto, essas limitações não necessariamente criam grandes problemas ou impedem o desenvolvimento sólido.

Você pode revisá-los a partir dos seguintes pontos -

  • Capacity Unit Sizes- Uma unidade de capacidade de leitura é uma única leitura consistente por segundo para itens não maiores que 4 KB. Uma unidade de capacidade de gravação é uma única gravação por segundo para itens não maiores que 1 KB.

  • Provisioned Throughput Min/Max- Todas as tabelas e índices secundários globais têm no mínimo uma unidade de capacidade de leitura e uma de gravação. Os máximos dependem da região. Nos EUA, 40K de leitura e gravação continuam sendo o limite por tabela (80K por conta), e outras regiões têm um limite de 10K por tabela com um limite de conta de 20K.

  • Provisioned Throughput Increase and Decrease - Você pode aumentar quantas vezes for necessário, mas as reduções permanecem limitadas a não mais do que quatro vezes ao dia por mesa.

  • Table Size and Quantity Per Account - Os tamanhos das tabelas não têm limites, mas as contas têm um limite de 256 mesas, a menos que você solicite um limite maior.

  • Secondary Indexes Per Table - Cinco locais e cinco globais são permitidos.

  • Projected Secondary Index Attributes Per Table - O DynamoDB permite 20 atributos.

  • Partition Key Length and Values - Seu comprimento mínimo é de 1 byte e máximo de 2.048 bytes; no entanto, o DynamoDB não impõe limites aos valores.

  • Sort Key Length and Values - Seu comprimento mínimo é de 1 byte e máximo de 1024 bytes, sem limite de valores, a menos que sua tabela use um índice secundário local.

  • Table and Secondary Index Names - Os nomes devem ter um comprimento mínimo de 3 caracteres e um máximo de 255. Eles usam os seguintes caracteres: AZ, az, 0-9, “_”, “-” e “.”.

  • Attribute Names - Um caractere permanece o mínimo e 64 KB o máximo, com exceções para chaves e certos atributos.

  • Reserved Words - O DynamoDB não impede o uso de palavras reservadas como nomes.

  • Expression Length- As strings de expressão têm um limite de 4 KB. As expressões de atributo têm um limite de 255 bytes. As variáveis ​​de substituição de uma expressão têm um limite de 2 MB.

Antes de usar o DynamoDB, você deve se familiarizar com seus componentes básicos e ecossistema. No ecossistema DynamoDB, você trabalha com tabelas, atributos e itens. Uma tabela contém conjuntos de itens e os itens contêm conjuntos de atributos. Um atributo é um elemento fundamental de dados que não requer decomposição adicional, ou seja, um campo.

Chave primária

As chaves primárias servem como meio de identificação exclusiva para itens de tabela, e os índices secundários fornecem flexibilidade de consulta. O DynamoDB transmite eventos de registro modificando os dados da tabela.

A Criação da Tabela requer não apenas a definição de um nome, mas também da chave primária; que identifica os itens da tabela. Não há dois itens que compartilhem uma chave. DynamoDB usa dois tipos de chaves primárias -

  • Partition Key- Esta chave primária simples consiste em um único atributo conhecido como "chave de partição". Internamente, o DynamoDB usa o valor da chave como entrada para uma função hash para determinar o armazenamento.

  • Partition Key and Sort Key - Esta chave, conhecida como “Chave primária composta”, consiste em dois atributos.

    • A chave de partição e

    • A chave de classificação.

    O DynamoDB aplica o primeiro atributo a uma função hash e armazena itens com a mesma chave de partição juntos; com sua ordem determinada pela chave de classificação. Os itens podem compartilhar chaves de partição, mas não chaves de classificação.

Os atributos de chave primária permitem apenas valores escalares (únicos); e string, número ou tipos de dados binários. Os atributos não-chave não têm essas restrições.

Índices Secundários

Esses índices permitem consultar os dados da tabela com uma chave alternativa. Embora o DynamoDB não force seu uso, eles otimizam a consulta.

DynamoDB usa dois tipos de índices secundários -

  • Global Secondary Index - Este índice possui chaves de partição e classificação, que podem ser diferentes das chaves de tabela.

  • Local Secondary Index - Este índice possui uma chave de partição idêntica à da tabela, porém sua chave de classificação é diferente.

API

As operações API oferecidas pelo DynamoDB incluem as do plano de controle, plano de dados (por exemplo, criação, leitura, atualização e exclusão) e fluxos. Nas operações de plano de controle, você cria e gerencia tabelas com as seguintes ferramentas -

  • CreateTable
  • DescribeTable
  • ListTables
  • UpdateTable
  • DeleteTable

No plano de dados, você executa operações CRUD com as seguintes ferramentas -

Crio Ler Atualizar Excluir

PutItem

BatchWriteItem

GetItem

BatchGetItem

Inquerir

Varredura

UpdateItem

Apagar item

BatchWriteItem

As operações de fluxo controlam os fluxos da tabela. Você pode revisar as seguintes ferramentas de fluxo -

  • ListStreams
  • DescribeStream
  • GetShardIterator
  • GetRecords

Taxa de transferência provisionada

Na criação da tabela, você especifica a taxa de transferência provisionada, que reserva recursos para leituras e gravações. Você usa unidades de capacidade para medir e definir o rendimento.

Quando os aplicativos excedem o rendimento definido, as solicitações falham. O console da GUI do DynamoDB permite monitorar a taxa de transferência definida e usada para um provisionamento melhor e dinâmico.

Consistência de leitura

DynamoDB usa eventually consistent e strongly consistentlê para oferecer suporte às necessidades de aplicativos dinâmicos. Leituras eventualmente consistentes nem sempre fornecem dados atuais.

As leituras fortemente consistentes sempre fornecem dados atuais (com exceção de falha de equipamento ou problemas de rede). Leituras eventualmente consistentes servem como configuração padrão, exigindo uma configuração de verdadeiro noConsistentRead parâmetro para alterá-lo.

Partições

O DynamoDB usa partições para armazenamento de dados. Essas alocações de armazenamento para tabelas têm suporte de SSD e são replicadas automaticamente nas zonas. O DynamoDB gerencia todas as tarefas de partição, não exigindo o envolvimento do usuário.

Na criação da tabela, a tabela entra no estado CREATING, que aloca as partições. Quando atinge o estado ATIVO, você pode realizar operações. O sistema altera as partições quando sua capacidade atinge o máximo ou quando você altera o rendimento.

O ambiente DynamoDB consiste apenas em usar sua conta Amazon Web Services para acessar o console da GUI do DynamoDB; no entanto, você também pode executar uma instalação local.

Navegue até o seguinte site - https://aws.amazon.com/dynamodb/

Clique no botão “Introdução ao Amazon DynamoDB” ou no botão “Criar uma conta AWS” se você não tiver uma conta Amazon Web Services. O processo simples e guiado informará você sobre todas as taxas e requisitos relacionados.

Após realizar todas as etapas necessárias do processo, você terá o acesso. Simplesmente entre no console AWS e navegue até o console DynamoDB.

Certifique-se de excluir o material não utilizado ou desnecessário para evitar taxas associadas.

Instalação local

O AWS (Amazon Web Service) fornece uma versão do DynamoDB para instalações locais. Ele suporta a criação de aplicativos sem o serviço da web ou uma conexão. Também reduz a taxa de transferência provisionada, armazenamento de dados e taxas de transferência, permitindo um banco de dados local. Este guia presume uma instalação local.

Quando estiver pronto para implantação, você pode fazer alguns pequenos ajustes em seu aplicativo para convertê-lo para uso da AWS.

O arquivo de instalação é um .jar executable. Ele roda em Linux, Unix, Windows e qualquer outro sistema operacional com suporte a Java. Baixe o arquivo usando um dos seguintes links -

  • Tarball - http://dynamodb-local.s3-website-us-west2.amazonaws.com/dynamodb_local_latest.tar.gz

  • Zip archive - http://dynamodb-local.s3-website-us-west2.amazonaws.com/dynamodb_local_latest.zip

Note- Outros repositórios oferecem o arquivo, mas não necessariamente a versão mais recente. Use os links acima para arquivos de instalação atualizados. Além disso, certifique-se de ter o Java Runtime Engine (JRE) versão 6.x ou uma versão mais recente. O DynamoDB não pode ser executado com versões anteriores.

Depois de baixar o arquivo apropriado, extraia seu diretório (DynamoDBLocal.jar) e coloque-o no local desejado.

Você pode então iniciar o DynamoDB abrindo um prompt de comando, navegando até o diretório que contém o DynamoDBLocal.jar e digitando o seguinte comando -

java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb

Você também pode parar o DynamoDB fechando o prompt de comando usado para iniciá-lo.

Ambiente de trabalho

Você pode usar um shell JavaScript, um console de GUI e vários idiomas para trabalhar com o DynamoDB. As linguagens disponíveis incluem Ruby, Java, Python, C #, Erlang, PHP e Perl.

Neste tutorial, usamos exemplos de console Java e GUI para clareza conceitual e de código. Instale um IDE Java, o AWS SDK para Java e configure as credenciais de segurança da AWS para o Java SDK a fim de utilizar Java.

Conversão de código de serviço local para Web

Quando estiver pronto para implantação, você precisará alterar seu código. Os ajustes dependem da linguagem do código e de outros fatores. A principal mudança consiste apenas em mudar oendpointde um ponto local para uma região AWS. Outras mudanças requerem uma análise mais profunda de seu aplicativo.

Uma instalação local difere do serviço da web de muitas maneiras, incluindo, mas não se limitando às seguintes diferenças principais -

  • A instalação local cria tabelas imediatamente, mas o serviço leva muito mais tempo.

  • A instalação local ignora a taxa de transferência.

  • A exclusão ocorre imediatamente em uma instalação local.

  • As leituras / gravações ocorrem rapidamente em instalações locais devido à ausência de sobrecarga de rede.

O DynamoDB oferece três opções para executar operações: um console GUI baseado na web, um shell JavaScript e uma linguagem de programação de sua escolha.

Neste tutorial, vamos nos concentrar no uso do console da GUI e da linguagem Java para maior clareza e compreensão conceitual.

Console GUI

O console da GUI ou o AWS Management Console para Amazon DynamoDB podem ser encontrados no seguinte endereço - https://console.aws.amazon.com/dynamodb/home

Ele permite que você execute as seguintes tarefas -

  • CRUD
  • Ver itens da tabela
  • Executar consultas de tabela
  • Definir alarmes para monitoramento da capacidade da mesa
  • Exibir métricas da tabela em tempo real
  • Ver Tabela de Alarmes

Se a sua conta DynamoDB não tiver tabelas, no acesso, ele o orienta na criação de uma tabela. Sua tela principal oferece três atalhos para realizar operações comuns -

  • Criar tabelas
  • Adicionar e consultar tabelas
  • Monitorar e gerenciar tabelas

O Shell JavaScript

O DynamoDB inclui um shell JavaScript interativo. O shell é executado em um navegador da web e os navegadores recomendados incluem Firefox e Chrome.

Note - Usar outros navegadores pode resultar em erros.

Acesse o shell abrindo um navegador da web e inserindo o seguinte endereço -http://localhost:8000/shell

Use o shell inserindo JavaScript no painel esquerdo e clicando no botão do ícone “Play” no canto superior direito do painel esquerdo, que executa o código. Os resultados do código são exibidos no painel direito.

DynamoDB e Java

Use Java com DynamoDB, utilizando seu ambiente de desenvolvimento Java. As operações confirmam a sintaxe e estrutura normal do Java.

Os tipos de dados suportados pelo DynamoDB incluem aqueles específicos para atributos, ações e sua linguagem de codificação de escolha.

Tipos de dados de atributos

O DynamoDB oferece suporte a um grande conjunto de tipos de dados para atributos de tabela. Cada tipo de dados se enquadra em uma das três categorias a seguir -

  • Scalar - Esses tipos representam um único valor e incluem número, string, binário, booleano e nulo.

  • Document - Esses tipos representam uma estrutura complexa que possui atributos aninhados e incluem listas e mapas.

  • Set - Esses tipos representam vários escalares e incluem conjuntos de strings, conjuntos de números e conjuntos binários.

Lembre-se do DynamoDB como um banco de dados NoSQL sem esquema que não precisa de definições de atributos ou tipos de dados ao criar uma tabela. Requer apenas tipos de dados de atributo de chave primária em contraste com RDBMS, que requer tipos de dados de coluna na criação da tabela.

Escalares

  • Numbers - Eles são limitados a 38 dígitos e são positivos, negativos ou zero.

  • String - São Unicode usando UTF-8, com comprimento mínimo> 0 e máximo de 400 KB.

  • Binary- Eles armazenam quaisquer dados binários, por exemplo, dados criptografados, imagens e texto compactado. O DynamoDB vê seus bytes como não assinados.

  • Boolean - Eles armazenam verdadeiro ou falso.

  • Null - Eles representam um estado desconhecido ou indefinido.

Documento

  • List - Armazena coleções de valores ordenados e usa colchetes ([...]).

  • Map - Ele armazena coleções de pares nome-valor não ordenados e usa chaves ({...}).

Conjunto

Os conjuntos devem conter elementos do mesmo tipo, sejam números, strings ou binários. Os únicos limites colocados em conjuntos consistem no limite de tamanho de item de 400 KB e cada elemento sendo único.

Tipos de dados de ação

A API do DynamoDB contém vários tipos de dados usados ​​por ações. Você pode revisar uma seleção dos seguintes tipos de chave -

  • AttributeDefinition - Representa tabela chave e esquema de índice.

  • Capacity - Representa a quantidade de throughput consumida por uma tabela ou índice.

  • CreateGlobalSecondaryIndexAction - Representa um novo índice secundário global adicionado a uma tabela.

  • LocalSecondaryIndex - Representa propriedades de índice secundário local.

  • ProvisionedThroughput - Representa a taxa de transferência provisionada para um índice ou tabela.

  • PutRequest - Representa solicitações PutItem.

  • TableDescription - Representa as propriedades da tabela.

Tipos de dados Java suportados

O DynamoDB fornece suporte para tipos de dados primitivos, coleções de conjuntos e tipos arbitrários para Java.

A criação de uma tabela geralmente consiste em gerar a tabela, nomeá-la, estabelecer seus atributos de chave primária e definir tipos de dados de atributo.

Utilize o console da GUI, Java ou outra opção para executar essas tarefas.

Criar tabela usando o console da GUI

Crie uma tabela acessando o console em https://console.aws.amazon.com/dynamodb. Em seguida, escolha a opção “Criar Tabela”.

Nosso exemplo gera uma tabela preenchida com informações do produto, com produtos de atributos únicos identificados por um número de identificação (atributo numérico). NoCreate Tabletela, insira o nome da tabela no campo de nome da tabela; insira a chave primária (ID) no campo da chave de partição; e digite “Número” para o tipo de dados.

Após inserir todas as informações, selecione Create.

Criar tabela usando Java

Use Java para criar a mesma tabela. Sua chave primária consiste nos dois atributos a seguir -

  • ID - Use uma chave de partição e o ScalarAttributeType N, significando número.

  • Nomenclature - Use uma chave de classificação e o ScalarAttributeType S, significando string.

Java usa o createTable methodpara gerar uma tabela; e dentro da chamada, nome da tabela, atributos de chave primária e tipos de dados de atributo são especificados.

Você pode revisar o seguinte exemplo -

import java.util.Arrays;
 
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; 
import com.amazonaws.services.dynamodbv2.document.DynamoDB; 
import com.amazonaws.services.dynamodbv2.document.Table; 

import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; 
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; 
import com.amazonaws.services.dynamodbv2.model.KeyType; 
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; 
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
 
public class ProductsCreateTable {  
   public static void main(String[] args) throws Exception { 
      AmazonDynamoDBClient client = new AmazonDynamoDBClient() 
         .withEndpoint("http://localhost:8000");  
      
      DynamoDB dynamoDB = new DynamoDB(client); 
      String tableName = "Products";  
      try { 
         System.out.println("Creating the table, wait..."); 
         Table table = dynamoDB.createTable (tableName, 
            Arrays.asList ( 
               new KeySchemaElement("ID", KeyType.HASH), // the partition key 
                                                         // the sort key 
               new KeySchemaElement("Nomenclature", KeyType.RANGE)
            ),
            Arrays.asList ( 
               new AttributeDefinition("ID", ScalarAttributeType.N), 
               new AttributeDefinition("Nomenclature", ScalarAttributeType.S)
            ),
            new ProvisionedThroughput(10L, 10L)
         );
         table.waitForActive(); 
         System.out.println("Table created successfully.  Status: " + 
            table.getDescription().getTableStatus());
            
      } catch (Exception e) {
         System.err.println("Cannot create the table: "); 
         System.err.println(e.getMessage()); 
      } 
   } 
}

No exemplo acima, observe o endpoint: .withEndpoint.

Indica o uso de uma instalação local usando o localhost. Além disso, observe o necessárioProvisionedThroughput parameter, que a instalação local ignora.

O carregamento de uma tabela geralmente consiste em criar um arquivo de origem, garantindo que o arquivo de origem esteja em conformidade com uma sintaxe compatível com o DynamoDB, enviar o arquivo de origem ao destino e, em seguida, confirmar uma população bem-sucedida.

Utilize o console da GUI, Java ou outra opção para executar a tarefa.

Carregar tabela usando o console da GUI

Carregue os dados usando uma combinação da linha de comando e do console. Você pode carregar dados de várias maneiras, algumas das quais são as seguintes -

  • O console
  • A linha de comando
  • Código e também
  • Pipeline de dados (um recurso discutido posteriormente no tutorial)

No entanto, para velocidade, este exemplo usa o shell e o console. Primeiro, carregue os dados de origem no destino com a seguinte sintaxe -

aws dynamodb batch-write-item -–request-items file://[filename]

Por exemplo -

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

Verifique o sucesso da operação acessando o console em -

https://console.aws.amazon.com/dynamodb

Escolher Tables no painel de navegação e selecione a tabela de destino na lista de tabelas.

Selecione os Itemspara examinar os dados usados ​​para preencher a tabela. SelecioneCancel para retornar à lista da mesa.

Carregar tabela usando Java

Empregue Java criando primeiro um arquivo de origem. Nosso arquivo de origem usa o formato JSON. Cada produto tem dois atributos-chave primários (ID e Nomenclatura) e um mapa JSON (Stat) -

[ 
   { 
      "ID" : ... , 
      "Nomenclature" : ... , 
      "Stat" : { ... }
   }, 
   { 
      "ID" : ... , 
      "Nomenclature" : ... , 
      "Stat" : { ... } 
   }, 
    ... 
]

Você pode revisar o seguinte exemplo -

{ 
   "ID" : 122, 
   "Nomenclature" : "Particle Blaster 5000", 
   "Stat" : { 
      "Manufacturer" : "XYZ Inc.", 
      "sales" : "1M+", 
      "quantity" : 500, 
      "img_src" : "http://www.xyz.com/manuals/particleblaster5000.jpg", 
      "description" : "A laser cutter used in plastic manufacturing." 
   } 
}

A próxima etapa é colocar o arquivo no diretório usado por seu aplicativo.

Java usa principalmente o putItem e path methods para realizar a carga.

Você pode revisar o seguinte exemplo de código para processar um arquivo e carregá-lo -

import java.io.File;
import java.util.Iterator;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.ObjectNode;

public class ProductsLoadData {  
   public static void main(String[] args) throws Exception {  
      AmazonDynamoDBClient client = new AmazonDynamoDBClient() 
         .withEndpoint("http://localhost:8000");  
      
      DynamoDB dynamoDB = new DynamoDB(client);  
      Table table = dynamoDB.getTable("Products");  
      JsonParser parser = new JsonFactory() 
         .createParser(new File("productinfo.json"));  
      
      JsonNode rootNode = new ObjectMapper().readTree(parser); 
      Iterator<JsonNode> iter = rootNode.iterator();  
      ObjectNode currentNode;  
      
      while (iter.hasNext()) { 
         currentNode = (ObjectNode) iter.next();  
         int ID = currentNode.path("ID").asInt(); 
         String Nomenclature = currentNode.path("Nomenclature").asText();  
         
         try { 
            table.putItem(new Item() 
               .withPrimaryKey("ID", ID, "Nomenclature", Nomenclature) 
               .withJSON("Stat", currentNode.path("Stat").toString()));
            System.out.println("Successful load: " + ID + " " + Nomenclature);  
         } catch (Exception e) {
            System.err.println("Cannot add product: " + ID + " " + Nomenclature);
            System.err.println(e.getMessage()); 
            break; 
         } 
      } 
      parser.close(); 
   } 
}

Consultar uma tabela requer principalmente a seleção de uma tabela, a especificação de uma chave de partição e a execução da consulta; com as opções de usar índices secundários e realizar uma filtragem mais profunda por meio de operações de varredura.

Utilize o console da GUI, Java ou outra opção para executar a tarefa.

Tabela de consulta usando o console da GUI

Execute algumas consultas simples usando as tabelas criadas anteriormente. Primeiro, abra o console emhttps://console.aws.amazon.com/dynamodb

Escolher Tables no painel de navegação e selecione Replyda lista da mesa. Em seguida, selecione oItems guia para ver os dados carregados.

Selecione o link de filtragem de dados (“Verificar: [Tabela] Responder”) abaixo do Create Item botão.

Na tela de filtragem, selecione Consulta para a operação. Insira o valor da chave de partição apropriada e clique emStart.

o Reply a tabela então retorna os itens correspondentes.

Tabela de consulta usando Java

Use o método de consulta em Java para executar operações de recuperação de dados. Requer a especificação do valor da chave de partição, com a chave de classificação como opcional.

Codifique uma consulta Java criando primeiro um querySpec objectdescrevendo parâmetros. Em seguida, passe o objeto para o método de consulta. Usamos a chave de partição dos exemplos anteriores.

Você pode revisar o seguinte exemplo -

import java.util.HashMap;
import java.util.Iterator;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;

public class ProductsQuery {  
   public static void main(String[] args) throws Exception {  
      AmazonDynamoDBClient client = new AmazonDynamoDBClient() 
         .withEndpoint("http://localhost:8000");  
      
      DynamoDB dynamoDB = new DynamoDB(client);  
      Table table = dynamoDB.getTable("Products");  
      HashMap<String, String> nameMap = new HashMap<String, String>(); 
      nameMap.put("#ID", "ID");  
      HashMap<String, Object> valueMap = new HashMap<String, Object>(); 
      valueMap.put(":xxx", 122);
      QuerySpec querySpec = new QuerySpec() 
         .withKeyConditionExpression("#ID = :xxx") 
         .withNameMap(new NameMap().with("#ID", "ID")) 
         .withValueMap(valueMap);  
      
      ItemCollection<QueryOutcome> items = null; 
      Iterator<Item> iterator = null; 
      Item item = null;  
      try { 
         System.out.println("Product with the ID 122"); 
         items = table.query(querySpec);  
         iterator = items.iterator(); 
         
         while (iterator.hasNext()) { 
            item = iterator.next(); 
            System.out.println(item.getNumber("ID") + ": " 
               + item.getString("Nomenclature")); 
         } 
      } catch (Exception e) { 
         System.err.println("Cannot find products with the ID number 122"); 
         System.err.println(e.getMessage()); 
      } 
   } 
}

Observe que a consulta usa a chave de partição, no entanto, os índices secundários fornecem outra opção para consultas. Sua flexibilidade permite a consulta de atributos não-chave, um tópico que será discutido posteriormente neste tutorial.

O método de varredura também oferece suporte a operações de recuperação reunindo todos os dados da tabela. ooptional .withFilterExpression evita que itens fora dos critérios especificados apareçam nos resultados.

Mais tarde neste tutorial, discutiremos scanningem detalhe. Agora, dê uma olhada no seguinte exemplo -

import java.util.Iterator;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.ScanOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.ScanSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;

public class ProductsScan {  
   public static void main(String[] args) throws Exception {  
      AmazonDynamoDBClient client = new AmazonDynamoDBClient() 
         .withEndpoint("http://localhost:8000");  
      
      DynamoDB dynamoDB = new DynamoDB(client);  
      Table table = dynamoDB.getTable("Products");  
      ScanSpec scanSpec = new ScanSpec() 
         .withProjectionExpression("#ID, Nomenclature , stat.sales") 
         .withFilterExpression("#ID between :start_id and :end_id") 
         .withNameMap(new NameMap().with("#ID",  "ID")) 
         .withValueMap(new ValueMap().withNumber(":start_id", 120)
         .withNumber(":end_id", 129));  
      
      try { 
         ItemCollection<ScanOutcome> items = table.scan(scanSpec);  
         Iterator<Item> iter = items.iterator(); 
        
         while (iter.hasNext()) {
            Item item = iter.next(); 
            System.out.println(item.toString()); 
         } 
      } catch (Exception e) { 
         System.err.println("Cannot perform a table scan:"); 
         System.err.println(e.getMessage()); 
      } 
   } 
}

Neste capítulo, discutiremos sobre como podemos excluir uma tabela e também as diferentes maneiras de excluir uma tabela.

A exclusão da tabela é uma operação simples que requer pouco mais do que o nome da tabela. Utilize o console da GUI, Java ou qualquer outra opção para executar esta tarefa.

Excluir tabela usando o console da GUI

Execute uma operação de exclusão acessando primeiro o console em -

https://console.aws.amazon.com/dynamodb.

Escolher Tables no painel de navegação e escolha a tabela desejada para exclusão da lista de tabelas, conforme mostrado na tela a seguir.

Finalmente, selecione Delete Table. Depois de escolher Excluir tabela, uma confirmação é exibida. Sua mesa é então excluída.

Excluir tabela usando Java

Use o deletemétodo para remover uma mesa. Um exemplo é dado abaixo para explicar melhor o conceito.

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; 
import com.amazonaws.services.dynamodbv2.document.DynamoDB; 
import com.amazonaws.services.dynamodbv2.document.Table;  

public class ProductsDeleteTable {  
   public static void main(String[] args) throws Exception {  
      AmazonDynamoDBClient client = new AmazonDynamoDBClient() 
         .withEndpoint("http://localhost:8000"); 
      
      DynamoDB dynamoDB = new DynamoDB(client);  
      Table table = dynamoDB.getTable("Products");  
      try { 
         System.out.println("Performing table delete, wait..."); 
         table.delete(); 
         table.waitForDelete(); 
         System.out.print("Table successfully deleted.");  
      } catch (Exception e) { 
         System.err.println("Cannot perform table delete: "); 
         System.err.println(e.getMessage()); 
      } 
   } 
}

O DynamoDB oferece um amplo conjunto de ferramentas API poderosas para manipulação de tabelas, leitura de dados e modificação de dados.

Amazon recomenda usar AWS SDKs(por exemplo, o Java SDK) em vez de chamar APIs de baixo nível. As bibliotecas tornam a interação com APIs de baixo nível diretamente desnecessária. As bibliotecas simplificam tarefas comuns, como autenticação, serialização e conexões.

Manipular tabelas

O DynamoDB oferece cinco ações de baixo nível para gerenciamento de mesa -

  • CreateTable- Isso gera uma tabela e inclui a taxa de transferência definida pelo usuário. Requer que você defina uma chave primária, seja composta ou simples. Também permite um ou vários índices secundários.

  • ListTables - Isso fornece uma lista de todas as tabelas na conta do usuário AWS atual e vinculadas ao seu terminal.

  • UpdateTable - Isso altera o rendimento e o rendimento do índice secundário global.

  • DescribeTable- Fornece metadados de tabela; por exemplo, estado, tamanho e índices.

  • DeleteTable - Isso simplesmente apaga a tabela e seus índices.

Ler dados

O DynamoDB oferece quatro ações de baixo nível para leitura de dados -

  • GetItem- Aceita uma chave primária e retorna atributos do item associado. Ele permite alterações em sua configuração de leitura padrão eventualmente consistente.

  • BatchGetItem- Executa várias solicitações GetItem em vários itens por meio de chaves primárias, com a opção de uma ou várias tabelas. Ele retorna no máximo 100 itens e deve permanecer abaixo de 16 MB. Permite leituras eventualmente consistentes e fortemente consistentes.

  • Scan- Lê todos os itens da tabela e produz um conjunto de resultados eventualmente consistente. Você pode filtrar os resultados por meio de condições. Ele evita o uso de um índice e verifica toda a tabela, portanto, não o use para consultas que requerem previsibilidade.

  • Query- Ele retorna um único ou vários itens de tabela ou itens de índice secundários. Ele usa um valor especificado para a chave de partição e permite o uso de operadores de comparação para estreitar o escopo. Inclui suporte para ambos os tipos de consistência e cada resposta obedece a um limite de 1 MB de tamanho.

Modificar Dados

O DynamoDB oferece quatro ações de baixo nível para modificação de dados -

  • PutItem- Isso gera um novo item ou substitui os itens existentes. Na descoberta de chaves primárias idênticas, por padrão, ele substitui o item. Os operadores condicionais permitem que você contorne o padrão e substitua itens apenas sob certas condições.

  • BatchWriteItem- Isso executa várias solicitações PutItem e DeleteItem e em várias tabelas. Se uma solicitação falhar, ela não afetará toda a operação. Seu limite é de 25 itens e 16 MB de tamanho.

  • UpdateItem - Altera os atributos de item existentes e permite o uso de operadores condicionais para executar atualizações apenas sob certas condições.

  • DeleteItem - Ele usa a chave primária para apagar um item e também permite o uso de operadores condicionais para especificar as condições de exclusão.

A criação de um item no DynamoDB consiste principalmente na especificação do item e do atributo e na opção de especificar condições. Cada item existe como um conjunto de atributos, com cada atributo nomeado e atribuído a um valor de um determinado tipo.

Os tipos de valor incluem escalar, documento ou conjunto. Os itens têm um limite de tamanho de 400 KB, com a possibilidade de qualquer quantidade de atributos capazes de caber dentro desse limite. Tamanhos de nome e valor (comprimentos binários e UTF-8) determinam o tamanho do item. O uso de nomes de atributos curtos ajuda a minimizar o tamanho do item.

Note- Você deve especificar todos os atributos de chave primária, com as chaves primárias exigindo apenas a chave de partição; e chaves compostas que requerem a partição e a chave de classificação.

Além disso, lembre-se de que as tabelas não possuem nenhum esquema predefinido. Você pode armazenar conjuntos de dados drasticamente diferentes em uma tabela.

Use o console da GUI, Java ou outra ferramenta para executar esta tarefa.

Como criar um item usando o console da GUI?

Navegue até o console. No painel de navegação do lado esquerdo, selecioneTables. Escolha o nome da tabela para usar como destino e selecione oItems guia como mostrado na imagem a seguir.

Selecione Create Item. A tela Criar item fornece uma interface para inserir os valores de atributo necessários. Quaisquer índices secundários também devem ser inseridos.

Se você precisar de mais atributos, selecione o menu de ação à esquerda do Message. Então selecioneAppende o tipo de dados desejado.

Depois de inserir todas as informações essenciais, selecione Save para adicionar o item.

Como usar o Java na criação de itens?

O uso de Java nas operações de criação de itens consiste em criar uma instância de classe DynamoDB, instância de classe Table, instância de classe Item e especificar a chave primária e os atributos do item que você criará. Em seguida, adicione seu novo item com o método putItem.

Exemplo

DynamoDB dynamoDB = new DynamoDB (new AmazonDynamoDBClient(
   new ProfileCredentialsProvider()));
Table table = dynamoDB.getTable("ProductList");
   
// Spawn a related items list 
List<Number> RELItems = new ArrayList<Number>(); 
RELItems.add(123); 
RELItems.add(456); 
RELItems.add(789);  
   
//Spawn a product picture map  
Map<String, String> photos = new HashMap<String, String>(); 
photos.put("Anterior", "http://xyz.com/products/101_front.jpg"); 
photos.put("Posterior", "http://xyz.com/products/101_back.jpg"); 
photos.put("Lateral", "http://xyz.com/products/101_LFTside.jpg");  

//Spawn a product review map 
Map<String, List<String>> prodReviews = new HashMap<String, List<String>>();  
List<String> fiveStarRVW = new ArrayList<String>(); 
fiveStarRVW.add("Shocking high performance."); 
fiveStarRVW.add("Unparalleled in its market."); 
prodReviews.put("5 Star", fiveStarRVW);  
List<String> oneStarRVW = new ArrayList<String>(); 
oneStarRVW.add("The worst offering in its market."); 
prodReviews.put("1 Star", oneStarRVW);  

// Generate the item 
Item item = new Item()
   .withPrimaryKey("Id", 101) 
   .withString("Nomenclature", "PolyBlaster 101") 
   .withString("Description", "101 description") 
   .withString("Category", "Hybrid Power Polymer Cutter")  
   .withString("Make", "Brand – XYZ") 
   .withNumber("Price", 50000) 
   .withString("ProductCategory", "Laser Cutter") 
   .withBoolean("Availability", true) 
   .withNull("Qty") 
   .withList("ItemsRelated", RELItems) 
   .withMap("Images", photos) 
   .withMap("Reviews", prodReviews);

// Add item to the table  
PutItemOutcome outcome = table.putItem(item);

Você também pode observar o seguinte exemplo maior.

Note- O exemplo a seguir pode assumir uma fonte de dados criada anteriormente. Antes de tentar executar, adquira bibliotecas de suporte e crie as fontes de dados necessárias (tabelas com as características necessárias ou outras fontes referenciadas).

O exemplo a seguir também usa Eclipse IDE, um arquivo de credenciais AWS e o AWS Toolkit em um projeto Eclipse AWS Java.

package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;

import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class CreateItemOpSample { 
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient ( 
      new ProfileCredentialsProvider()));  
   static String tblName = "ProductList";  
      
   public static void main(String[] args) throws IOException {  
      createItems();  
      retrieveItem();  
         
      // Execute updates 
      updateMultipleAttributes(); 
      updateAddNewAttribute(); 
      updateExistingAttributeConditionally();  
         
      // Item deletion 
      deleteItem();  
   }
   private static void createItems() {  
      Table table = dynamoDB.getTable(tblName); 
      try {  
         Item item = new Item() 
            .withPrimaryKey("ID", 303)
            .withString("Nomenclature", "Polymer Blaster 4000") 
            .withStringSet( "Manufacturers", 
            new HashSet<String>(Arrays.asList("XYZ Inc.", "LMNOP Inc.")))  
            .withNumber("Price", 50000) 
            .withBoolean("InProduction", true) 
            .withString("Category", "Laser Cutter"); 
         
         table.putItem(item);  
         item = new Item() 
            .withPrimaryKey("ID", 313) 
            .withString("Nomenclature", "Agitatatron 2000") 
            .withStringSet( "Manufacturers", 
            new HashSet<String>(Arrays.asList("XYZ Inc,", "CDE Inc."))) 
            .withNumber("Price", 40000) 
            .withBoolean("InProduction", true) 
            .withString("Category", "Agitator"); 
         
         table.putItem(item);  
      } catch (Exception e) { 
         System.err.println("Cannot create items."); 
         System.err.println(e.getMessage()); 
      } 
   }   
}

A recuperação de um item no DynamoDB requer o uso de GetItem e a especificação do nome da tabela e da chave primária do item. Certifique-se de incluir uma chave primária completa em vez de omitir uma parte.

Por exemplo, omitir a chave de classificação de uma chave composta.

O comportamento de GetItem está em conformidade com três padrões -

  • Ele é executado como uma leitura eventualmente consistente.
  • Ele fornece todos os atributos.
  • Não detalha o consumo da unidade de capacidade.

Esses parâmetros permitem que você substitua o comportamento padrão de GetItem.

Recuperar um Item

O DynamoDB garante confiabilidade por meio da manutenção de várias cópias de itens em vários servidores. Cada gravação bem-sucedida cria essas cópias, mas leva um tempo considerável para ser executada; significado eventualmente consistente. Isso significa que você não pode tentar uma leitura imediatamente após escrever um item.

Você pode alterar a leitura padrão eventualmente consistente de GetItem, no entanto, o custo de dados mais atuais continua sendo o consumo de mais unidades de capacidade; especificamente, duas vezes mais. Observação O DynamoDB normalmente atinge consistência em todas as cópias em um segundo.

Você pode usar o console da GUI, Java ou outra ferramenta para executar esta tarefa.

Recuperação de item usando Java

Usar Java em operações de recuperação de item requer a criação de uma instância de classe DynamoDB, instância de classe de tabela e chamar o método getItem da instância de tabela. Em seguida, especifique a chave primária do item.

Você pode revisar o seguinte exemplo -

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));  
Table table = dynamoDB.getTable("ProductList");  
Item item = table.getItem("IDnum", 109);

Em alguns casos, você precisa especificar os parâmetros para esta operação.

O exemplo a seguir usa .withProjectionExpression e GetItemSpec para especificações de recuperação -

GetItemSpec spec = new GetItemSpec() 
   .withPrimaryKey("IDnum", 122) 
   .withProjectionExpression("IDnum, EmployeeName, Department") 
   .withConsistentRead(true);

Item item = table.getItem(spec);
System.out.println(item.toJSONPretty());

Você também pode revisar o seguinte exemplo maior para melhor compreensão.

Note- O exemplo a seguir pode assumir uma fonte de dados criada anteriormente. Antes de tentar executar, adquira bibliotecas de suporte e crie as fontes de dados necessárias (tabelas com as características necessárias ou outras fontes referenciadas).

Este exemplo também usa Eclipse IDE, um arquivo de credenciais da AWS e o AWS Toolkit em um projeto Eclipse AWS Java.

package com.amazonaws.codesamples.document;

import java.io.IOException
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;

import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class GetItemOpSample {
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
      new ProfileCredentialsProvider()));
   
   static String tblName = "ProductList";
   public static void main(String[] args) throws IOException {
      createItems();
      retrieveItem();
      
      // Execute updates
      updateMultipleAttributes();
      updateAddNewAttribute();
      updateExistingAttributeConditionally();
      
      // Item deletion
      deleteItem();
   }
   private static void createItems() {
      Table table = dynamoDB.getTable(tblName);
      try {
         Item item = new Item()
            .withPrimaryKey("ID", 303)
            .withString("Nomenclature", "Polymer Blaster 4000")
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc.", "LMNOP Inc.")))
            .withNumber("Price", 50000)
            .withBoolean("InProduction", true)
            .withString("Category", "Laser Cutter");
            table.putItem(item);
            
         item = new Item()
            .withPrimaryKey("ID", 313)
            .withString("Nomenclature", "Agitatatron 2000")
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc,", "CDE Inc.")))
            .withNumber("Price", 40000)
            .withBoolean("InProduction", true)
            .withString("Category", "Agitator");
         
         table.putItem(item);
      } catch (Exception e) {
         System.err.println("Cannot create items.");
         System.err.println(e.getMessage());
      }
   }
   private static void retrieveItem() {
      Table table = dynamoDB.getTable(tableName);
      try {
         Item item = table.getItem("ID", 303, "ID, Nomenclature, Manufacturers", null);
         System.out.println("Displaying retrieved items...");
         System.out.println(item.toJSONPretty());
      } catch (Exception e) {
         System.err.println("Cannot retrieve items.");
         System.err.println(e.getMessage());
      }
   }
}

Atualizar um item no DynamoDB consiste principalmente em especificar a chave primária completa e o nome da tabela para o item. Requer um novo valor para cada atributo modificado. A operação usaUpdateItem, que modifica os itens existentes ou os cria ao descobrir um item ausente.

Nas atualizações, você pode querer rastrear as alterações exibindo os valores originais e novos, antes e depois das operações. UpdateItem usa oReturnValues parâmetro para conseguir isso.

Note - A operação não relata o consumo da unidade de capacidade, mas você pode usar o ReturnConsumedCapacity parâmetro.

Use o console da GUI, Java ou qualquer outra ferramenta para executar esta tarefa.

Como atualizar itens usando ferramentas GUI?

Navegue até o console. No painel de navegação do lado esquerdo, selecioneTables. Escolha a mesa necessária e selecione oItems aba.

Escolha o item desejado para uma atualização e selecione Actions | Edit.

Modifique quaisquer atributos ou valores necessários no Edit Item janela.

Atualizar itens usando Java

Usar Java nas operações de atualização do item requer a criação de uma instância da classe Table e a chamada de seu updateItemmétodo. Em seguida, você especifica a chave primária do item e fornece umUpdateExpression detalhando modificações de atributos.

O seguinte é um exemplo do mesmo -

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient(
   new ProfileCredentialsProvider()));
   
Table table = dynamoDB.getTable("ProductList");

Map<String, String> expressionAttributeNames = new HashMap<String, String>();
expressionAttributeNames.put("#M", "Make");
expressionAttributeNames.put("#P", "Price
expressionAttributeNames.put("#N", "ID");

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":val1",
   new HashSet<String>(Arrays.asList("Make1","Make2")));
expressionAttributeValues.put(":val2", 1);       //Price

UpdateItemOutcome outcome =  table.updateItem(
   "internalID",                                 // key attribute name
   111,                                          // key attribute value
   "add #M :val1 set #P = #P - :val2 remove #N", // UpdateExpression
   expressionAttributeNames,
   expressionAttributeValues);

o updateItem método também permite especificar condições, que podem ser vistas no exemplo a seguir -

Table table = dynamoDB.getTable("ProductList");
Map<String, String> expressionAttributeNames = new HashMap<String, String>();
expressionAttributeNames.put("#P", "Price");

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":val1", 44);  // change Price to 44
expressionAttributeValues.put(":val2", 15);  // only if currently 15

UpdateItemOutcome outcome = table.updateItem (new PrimaryKey("internalID",111),
   "set #P = :val1",                        // Update
   "#P = :val2",                            // Condition 
   expressionAttributeNames,
   expressionAttributeValues);

Atualizar itens usando contadores

O DynamoDB permite contadores atômicos, o que significa usar UpdateItem para aumentar / diminuir os valores dos atributos sem impactar outras solicitações; além disso, os contadores sempre são atualizados.

A seguir está um exemplo que explica como isso pode ser feito.

Note- O exemplo a seguir pode assumir uma fonte de dados criada anteriormente. Antes de tentar executar, adquira bibliotecas de suporte e crie as fontes de dados necessárias (tabelas com as características necessárias ou outras fontes referenciadas).

Este exemplo também usa Eclipse IDE, um arquivo de credenciais da AWS e o AWS Toolkit em um projeto Eclipse AWS Java.

package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;

import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class UpdateItemOpSample {  
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
      new ProfileCredentialsProvider()));  
   static String tblName = "ProductList";  
   
   public static void main(String[] args) throws IOException {  
      createItems();  
      retrieveItem();  
      
      // Execute updates 
      updateMultipleAttributes(); 
      updateAddNewAttribute();
      updateExistingAttributeConditionally();  
      
      // Item deletion 
      deleteItem(); 
   }
   private static void createItems() {  
      Table table = dynamoDB.getTable(tblName); 
      try { 
         Item item = new Item() 
            .withPrimaryKey("ID", 303) 
            .withString("Nomenclature", "Polymer Blaster 4000") 
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc.", "LMNOP Inc."))) 
            .withNumber("Price", 50000) 
            .withBoolean("InProduction", true) 
            .withString("Category", "Laser Cutter"); 
            table.putItem(item);  
         
         item = new Item() 
            .withPrimaryKey("ID", 313) 
            .withString("Nomenclature", "Agitatatron 2000") 
            .withStringSet( "Manufacturers", 
            new HashSet<String>(Arrays.asList("XYZ Inc,", "CDE Inc."))) 
            .withNumber("Price", 40000) 
            .withBoolean("InProduction", true) 
            .withString("Category", "Agitator");  
            table.putItem(item);  
      } catch (Exception e) { 
         System.err.println("Cannot create items."); 
         System.err.println(e.getMessage()); 
      } 
   }
   private static void updateAddNewAttribute() { 
      Table table = dynamoDB.getTable(tableName);  
      try {  
         Map<String, String> expressionAttributeNames = new HashMap<String, String>(); 
         expressionAttributeNames.put("#na", "NewAttribute");  
         UpdateItemSpec updateItemSpec = new UpdateItemSpec() 
            .withPrimaryKey("ID", 303) 
            .withUpdateExpression("set #na = :val1") 
            .withNameMap(new NameMap() 
            .with("#na", "NewAttribute")) 
            .withValueMap(new ValueMap() 
            .withString(":val1", "A value")) 
            .withReturnValues(ReturnValue.ALL_NEW);  
            UpdateItemOutcome outcome =  table.updateItem(updateItemSpec);  
         
         // Confirm 
         System.out.println("Displaying updated item..."); 
         System.out.println(outcome.getItem().toJSONPretty());             
      } catch (Exception e) { 
         System.err.println("Cannot add an attribute in " + tableName); 
         System.err.println(e.getMessage()); 
      }         
   } 
}

A exclusão de um item no DynamoDB requer apenas o fornecimento do nome da tabela e da chave do item. Também é altamente recomendado o uso de uma expressão condicional que será necessária para evitar a exclusão de itens errados.

Como de costume, você pode usar o console da GUI, Java ou qualquer outra ferramenta necessária para executar esta tarefa.

Excluir itens usando o console da GUI

Navegue até o console. No painel de navegação do lado esquerdo, selecioneTables. Em seguida, selecione o nome da tabela e oItems aba.

Escolha os itens desejados para exclusão e selecione Actions | Delete.

UMA Delete Item(s)a caixa de diálogo aparecerá conforme mostrado na captura de tela a seguir. Escolha “Excluir” para confirmar.

Como excluir itens usando Java?

O uso de Java em operações de exclusão de itens envolve apenas a criação de uma instância do cliente DynamoDB e a chamada do deleteItem método através do uso da chave do item.

Você pode ver o seguinte exemplo, onde foi explicado em detalhes.

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));
   
Table table = dynamoDB.getTable("ProductList");
DeleteItemOutcome outcome = table.deleteItem("IDnum", 151);

Você também pode especificar os parâmetros para proteção contra exclusão incorreta. Basta usar umConditionExpression.

Por exemplo -

Map<String,Object> expressionAttributeValues = new HashMap<String,Object>(); 
expressionAttributeValues.put(":val", false);
  
DeleteItemOutcome outcome = table.deleteItem("IDnum",151, 
   "Ship = :val",  
   null,                   // doesn't use ExpressionAttributeNames  
   expressionAttributeValues);

A seguir está um exemplo maior para melhor compreensão.

Note- O exemplo a seguir pode assumir uma fonte de dados criada anteriormente. Antes de tentar executar, adquira bibliotecas de suporte e crie as fontes de dados necessárias (tabelas com as características necessárias ou outras fontes referenciadas).

Este exemplo também usa Eclipse IDE, um arquivo de credenciais da AWS e o AWS Toolkit em um projeto Eclipse AWS Java.

package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;

import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class DeleteItemOpSample {  
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
      new ProfileCredentialsProvider()));  
   
   static String tblName = "ProductList";  
   public static void main(String[] args) throws IOException { 
      createItems(); 
      retrieveItem();  
      
      // Execute updates 
      updateMultipleAttributes(); 
      updateAddNewAttribute(); 
      updateExistingAttributeConditionally();  
      
      // Item deletion 
      deleteItem();  
   }  
   private static void createItems() {  
      Table table = dynamoDB.getTable(tblName); 
      try {  
         Item item = new Item()  
            .withPrimaryKey("ID", 303) 
            .withString("Nomenclature", "Polymer Blaster 4000")
            .withStringSet( "Manufacturers",
            new HashSet<String>(Arrays.asList("XYZ Inc.", "LMNOP Inc."))) 
            .withNumber("Price", 50000) 
            .withBoolean("InProduction", true) 
            .withString("Category", "Laser Cutter"); 
            table.putItem(item);  
         
         item = new Item() 
            .withPrimaryKey("ID", 313) 
            .withString("Nomenclature", "Agitatatron 2000") 
            .withStringSet( "Manufacturers", 
            new HashSet<String>(Arrays.asList("XYZ Inc,", "CDE Inc."))) 
            .withNumber("Price", 40000) 
            .withBoolean("InProduction", true) 
            .withString("Category", "Agitator"); 
            table.putItem(item);  
      } catch (Exception e) { 
         System.err.println("Cannot create items."); 
         System.err.println(e.getMessage());  
      } 
   }  
   private static void deleteItem() {  
      Table table = dynamoDB.getTable(tableName);  
      try {  
         DeleteItemSpec deleteItemSpec = new DeleteItemSpec() 
            .withPrimaryKey("ID", 303)  
            .withConditionExpression("#ip = :val") 
            .withNameMap(new NameMap() 
            .with("#ip", "InProduction"))
            .withValueMap(new ValueMap() 
            .withBoolean(":val", false)) 
            .withReturnValues(ReturnValue.ALL_OLD);  
         DeleteItemOutcome outcome = table.deleteItem(deleteItemSpec);  
         
         // Confirm 
         System.out.println("Displaying deleted item..."); 
         System.out.println(outcome.getItem().toJSONPretty());  
      } catch (Exception e) { 
         System.err.println("Cannot delete item in " + tableName); 
         System.err.println(e.getMessage()); 
      } 
   } 
}

A gravação em lote opera em vários itens, criando ou excluindo vários itens. Essas operações utilizamBatchWriteItem, que carrega as limitações de no máximo 16 MB de gravações e 25 solicitações. Cada item obedece a um limite de tamanho de 400 KB. As gravações em lote também não podem realizar atualizações de itens.

O que é escrita em lote?

As gravações em lote podem manipular itens em várias tabelas. A invocação da operação acontece para cada solicitação individual, o que significa que as operações não afetam umas às outras e combinações heterogêneas são permitidas; por exemplo, umPutItem e três DeleteItemsolicitações em lote, com a falha da solicitação PutItem não afetando as outras. As solicitações com falha resultam na operação de retorno de informações (chaves e dados) pertencentes a cada solicitação com falha.

Note- Se o DynamoDB retornar algum item sem processá-lo, tente novamente; no entanto, use um método de retirada para evitar outra falha de solicitação com base na sobrecarga.

O DynamoDB rejeita uma operação de gravação em lote quando uma ou mais das seguintes afirmações se comprovam verdadeiras -

  • A solicitação excede a taxa de transferência provisionada.

  • A solicitação tenta usar BatchWriteItems para atualizar um item.

  • A solicitação executa várias operações em um único item.

  • As tabelas de solicitação não existem.

  • Os atributos do item na solicitação não correspondem ao destino.

  • As solicitações excedem os limites de tamanho.

As gravações em lote exigem certas RequestItem parâmetros -

  • As operações de exclusão precisam DeleteRequest chave subelements significando um nome e valor de atributo.

  • o PutRequest itens requerem um Item subelement significando um atributo e um mapa de valor de atributo.

Response - Uma operação bem-sucedida resulta em uma resposta HTTP 200, que indica características como unidades de capacidade consumidas, métricas de processamento de tabela e quaisquer itens não processados.

Gravações em lote com Java

Execute uma gravação em lote criando uma instância de classe DynamoDB, um TableWriteItems instância de classe descrevendo todas as operações e chamando o batchWriteItem método para usar o objeto TableWriteItems.

Note- Você deve criar uma instância TableWriteItems para cada tabela em uma gravação em lote em várias tabelas. Além disso, verifique sua resposta de solicitação para quaisquer solicitações não processadas.

Você pode revisar o seguinte exemplo de gravação em lote -

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));  

TableWriteItems forumTableWriteItems = new TableWriteItems("Forum") 
   .withItemsToPut( 
   new Item() 
   .withPrimaryKey("Title", "XYZ CRM") 
   .withNumber("Threads", 0));  

TableWriteItems threadTableWriteItems = new TableWriteItems(Thread) 
   .withItemsToPut( 
   new Item() 
   .withPrimaryKey("ForumTitle","XYZ CRM","Topic","Updates") 
   .withHashAndRangeKeysToDelete("ForumTitle","A partition key value", 
   "Product Line 1", "A sort key value"));

BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem (
   forumTableWriteItems, threadTableWriteItems);

O programa a seguir é outro exemplo maior para melhor compreensão de como um lote grava com Java.

Note- O exemplo a seguir pode assumir uma fonte de dados criada anteriormente. Antes de tentar executar, adquira bibliotecas de suporte e crie as fontes de dados necessárias (tabelas com as características necessárias ou outras fontes referenciadas).

Este exemplo também usa Eclipse IDE, um arquivo de credenciais AWS e o AWS Toolkit em um projeto Eclipse AWS Java.

package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.BatchWriteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.TableWriteItems;
import com.amazonaws.services.dynamodbv2.model.WriteRequest;

public class BatchWriteOpSample {  
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
      new ProfileCredentialsProvider()));  
   static String forumTableName = "Forum"; 
   static String threadTableName = "Thread";  
      
   public static void main(String[] args) throws IOException { 
      batchWriteMultiItems();   
   }
   private static void batchWriteMultiItems() { 
      try {
         // Place new item in Forum 
         TableWriteItems forumTableWriteItems = new TableWriteItems(forumTableName) 
                                                                       //Forum 
            .withItemsToPut(new Item() 
            .withPrimaryKey("Name", "Amazon RDS") 
            .withNumber("Threads", 0));  
            
         // Place one item, delete another in Thread 
         // Specify partition key and range key 
         TableWriteItems threadTableWriteItems = new TableWriteItems(threadTableName) 
            .withItemsToPut(new Item() 
            .withPrimaryKey("ForumName","Product  
            Support","Subject","Support Thread 1") 
            .withString("Message", "New OS Thread 1 message")
            .withHashAndRangeKeysToDelete("ForumName","Subject", "Polymer Blaster", 
            "Support Thread 100"));  
            
         System.out.println("Processing request..."); 
         BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem (
               forumTableWriteItems, threadTableWriteItems);
         do {  
            // Confirm no unprocessed items 
            Map<String, List<WriteRequest>> unprocessedItems 
               = outcome.getUnprocessedItems();  
                  
            if (outcome.getUnprocessedItems().size() == 0) { 
               System.out.println("All items processed."); 
            } else { 
               System.out.println("Gathering unprocessed items..."); 
               outcome = dynamoDB.batchWriteItemUnprocessed(unprocessedItems); 
            }  
         } while (outcome.getUnprocessedItems().size() > 0);  
      } catch (Exception e) { 
         System.err.println("Could not get items: "); 
         e.printStackTrace(System.err); 
      }   
   } 
}

As operações de recuperação em lote retornam atributos de um único item ou de vários itens. Essas operações geralmente consistem em usar a chave primária para identificar o (s) item (ns) desejado (s). oBatchGetItem as operações estão sujeitas aos limites das operações individuais, bem como às suas próprias restrições exclusivas.

As seguintes solicitações em operações de recuperação em lote resultam em rejeição -

  • Faça uma solicitação de mais de 100 itens.
  • Faça uma solicitação que exceda a taxa de transferência.

As operações de recuperação em lote executam processamento parcial de solicitações com potencial de exceder os limites.

For example- uma solicitação para recuperar vários itens grandes o suficiente em tamanho para ultrapassar os limites resulta em parte do processamento da solicitação e uma mensagem de erro indicando a parte não processada. Na devolução de itens não processados, crie uma solução de algoritmo de retirada para gerenciar isso, em vez de tabelas de limitação.

o BatchGetas operações executam eventualmente com leituras consistentes, exigindo modificação para leituras fortemente consistentes. Eles também realizam recuperações em paralelo.

Note- A ordem dos itens devolvidos. O DynamoDB não classifica os itens. Também não indica a ausência dos itens solicitados. Além disso, essas solicitações consomem unidades de capacidade.

Todas as operações BatchGet exigem RequestItems parâmetros como consistência de leitura, nomes de atributos e chaves primárias.

Response - Uma operação bem-sucedida resulta em uma resposta HTTP 200, que indica características como unidades de capacidade consumidas, métricas de processamento de tabela e quaisquer itens não processados.

Recuperações em lote com Java

Usar Java em operações BatchGet requer a criação de uma instância de classe DynamoDB, TableKeysAndAttributes instância de classe descrevendo uma lista de valores de chave primária para os itens e passando o objeto TableKeysAndAttributes para o BatchGetItem método.

A seguir está um exemplo de uma operação BatchGet -

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient ( 
   new ProfileCredentialsProvider()));  

TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes 
   (forumTableName);
   
forumTableKeysAndAttributes.addHashOnlyPrimaryKeys (
   "Title",
   "Updates",  
   "Product Line 1"
); 
TableKeysAndAttributes threadTableKeysAndAttributes = new TableKeysAndAttributes (
   threadTableName);
      
threadTableKeysAndAttributes.addHashAndRangePrimaryKeys (
   "ForumTitle",
   "Topic",  
   "Product Line 1",
   "P1 Thread 1", 
   "Product Line 1",
   "P1 Thread 2", 
   "Product Line 2",
   "P2 Thread 1"
); 
BatchGetItemOutcome outcome = dynamoDB.batchGetItem ( 
   forumTableKeysAndAttributes, threadTableKeysAndAttributes);
      
for (String tableName : outcome.getTableItems().keySet()) { 
   System.out.println("Table items " + tableName); 
   List<Item> items = outcome.getTableItems().get(tableName); 
   for (Item item : items) { 
      System.out.println(item); 
   } 
}

Você pode revisar o seguinte exemplo maior.

Note- O programa a seguir pode assumir uma fonte de dados criada anteriormente. Antes de tentar executar, adquira bibliotecas de suporte e crie as fontes de dados necessárias (tabelas com as características necessárias ou outras fontes referenciadas).

Este programa também usa Eclipse IDE, um arquivo de credenciais AWS e o AWS Toolkit em um projeto Eclipse AWS Java.

package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.BatchGetItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.TableKeysAndAttributes;
import com.amazonaws.services.dynamodbv2.model.KeysAndAttributes;

public class BatchGetOpSample { 
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient ( 
      new ProfileCredentialsProvider())); 
      
   static String forumTableName = "Forum"; 
   static String threadTableName = "Thread"; 
     
   public static void main(String[] args) throws IOException { 
      retrieveMultipleItemsBatchGet(); 
   }
   private static void retrieveMultipleItemsBatchGet() {         
      try { 
         TableKeysAndAttributes forumTableKeysAndAttributes = 
            new TableKeysAndAttributes(forumTableName); 
         
         //Create partition key 
         forumTableKeysAndAttributes.addHashOnlyPrimaryKeys (
            "Name", 
            "XYZ Melt-O-tron", 
            "High-Performance Processing"
         ); 
         TableKeysAndAttributes threadTableKeysAndAttributes = 
            new TableKeysAndAttributes(threadTableName); 
         
         //Create partition key and sort key 
         threadTableKeysAndAttributes.addHashAndRangePrimaryKeys (
            "ForumName",
            "Subject",  
            "High-Performance Processing",
            "HP Processing Thread One", 
            "High-Performance Processing",
            "HP Processing Thread Two", 
            "Melt-O-Tron",
            "MeltO Thread One"
         );
         System.out.println("Processing..."); 
         BatchGetItemOutcome outcome = dynamoDB.batchGetItem(forumTableKeysAndAttributes,
            threadTableKeysAndAttributes); 
              
         Map<String, KeysAndAttributes> unprocessed = null;    
         do { 
            for (String tableName : outcome.getTableItems().keySet()) { 
               System.out.println("Table items for " + tableName); 
               List<Item> items = outcome.getTableItems().get(tableName); 
               
               for (Item item : items) { 
                  System.out.println(item.toJSONPretty()); 
               } 
            } 
            // Confirm no unprocessed items 
            unprocessed = outcome.getUnprocessedKeys(); 
                 
            if (unprocessed.isEmpty()) { 
               System.out.println("All items processed."); 
            } else { 
               System.out.println("Gathering unprocessed items..."); 
               outcome = dynamoDB.batchGetItemUnprocessed(unprocessed); 
            } 
         } while (!unprocessed.isEmpty()); 
      } catch (Exception e) { 
         System.err.println("Could not get items."); 
         System.err.println(e.getMessage()); 
      }   
   } 
}

As consultas localizam itens ou índices secundários por meio de chaves primárias. A execução de uma consulta requer uma chave de partição e um valor específico ou uma chave e um valor de classificação; com a opção de filtrar com comparações. O comportamento padrão de uma consulta consiste em retornar todos os atributos dos itens associados à chave primária fornecida. No entanto, você pode especificar os atributos desejados com oProjectionExpression parâmetro.

Uma consulta utiliza o KeyConditionExpressionparâmetros para selecionar itens, o que requer fornecer o nome da chave de partição e o valor na forma de uma condição de igualdade. Você também tem a opção de fornecer uma condição adicional para quaisquer chaves de classificação presentes.

Alguns exemplos das condições-chave de classificação são -

Sr. Não Condição e descrição
1

x = y

Ele é avaliado como verdadeiro se o atributo x for igual a y.

2

x < y

Ele avalia como verdadeiro se x for menor que y.

3

x <= y

Ele avalia como verdadeiro se x for menor ou igual a y.

4

x > y

Ele avalia como verdadeiro se x for maior que y.

5

x >= y

Ele avalia como verdadeiro se x for maior ou igual a y.

6

x BETWEEN y AND z

Ele avalia como verdadeiro se x for> = y e <= z.

O DynamoDB também oferece suporte às seguintes funções: begins_with (x, substr)

Ele é avaliado como verdadeiro se o atributo x começar com a string especificada.

As seguintes condições devem estar em conformidade com certos requisitos -

  • Os nomes de atributos devem começar com um caractere dentro do conjunto az ou AZ.

  • O segundo caractere de um nome de atributo deve estar no conjunto az, AZ ou 0-9.

  • Nomes de atributos não podem usar palavras reservadas.

Nomes de atributos fora de conformidade com as restrições acima podem definir um espaço reservado.

A consulta é processada executando recuperações em ordem de chave de classificação e usando qualquer condição e expressão de filtro presente. As consultas sempre retornam um conjunto de resultados e, em nenhuma correspondência, retorna um conjunto vazio.

Os resultados sempre retornam na ordem da chave de classificação e na ordem baseada no tipo de dados, com o padrão modificável em ordem crescente.

Consultando com Java

As consultas em Java permitem que você consulte tabelas e índices secundários. Eles exigem a especificação de chaves de partição e condições de igualdade, com a opção de especificar chaves de classificação e condições.

As etapas gerais necessárias para uma consulta em Java incluem a criação de uma instância da classe DynamoDB, instância da classe Table para a tabela de destino e chamada do método de consulta da instância Table para receber o objeto de consulta.

A resposta à consulta contém um ItemCollection objeto fornecendo todos os itens devolvidos.

O exemplo a seguir demonstra uma consulta detalhada -

DynamoDB dynamoDB = new DynamoDB (
   new AmazonDynamoDBClient(new ProfileCredentialsProvider()));

Table table = dynamoDB.getTable("Response");  
   QuerySpec spec = new QuerySpec() 
   .withKeyConditionExpression("ID = :nn") 
.withValueMap(new ValueMap() 
   .withString(":nn", "Product Line 1#P1 Thread 1"));
   
ItemCollection<QueryOutcome> items = table.query(spec);  
Iterator<Item> iterator = items.iterator(); 
Item item = null; 

while (iterator.hasNext()) { 
   item = iterator.next(); 
   System.out.println(item.toJSONPretty());
}

O método de consulta oferece suporte a uma ampla variedade de parâmetros opcionais. O exemplo a seguir demonstra como utilizar esses parâmetros -

Table table = dynamoDB.getTable("Response");  
QuerySpec spec = new QuerySpec() 
   .withKeyConditionExpression("ID = :nn and ResponseTM > :nn_responseTM")  
   .withFilterExpression("Author = :nn_author") 
   .withValueMap(new ValueMap()
   .withString(":nn", "Product Line 1#P1 Thread 1") 
   .withString(":nn_responseTM", twoWeeksAgoStr) 
   .withString(":nn_author", "Member 123"))
   .withConsistentRead(true);
   
ItemCollection<QueryOutcome> items = table.query(spec);  
Iterator<Item> iterator = items.iterator(); 

while (iterator.hasNext()) { 
   System.out.println(iterator.next().toJSONPretty()); 
}

Você também pode revisar o seguinte exemplo maior.

Note- O programa a seguir pode assumir uma fonte de dados criada anteriormente. Antes de tentar executar, adquira bibliotecas de suporte e crie as fontes de dados necessárias (tabelas com as características necessárias ou outras fontes referenciadas).

Este exemplo também usa Eclipse IDE, um arquivo de credenciais AWS e o AWS Toolkit em um projeto Eclipse AWS Java.

package com.amazonaws.codesamples.document;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;

import com.amazonaws.services.dynamodbv2.document.Page;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;

public class QueryOpSample {
   static DynamoDB dynamoDB = new DynamoDB(
      new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
   static String tableName = "Reply";  
   
   public static void main(String[] args) throws Exception { 
      String forumName = "PolyBlaster"; 
      String threadSubject = "PolyBlaster Thread 1";  
      getThreadReplies(forumName, threadSubject); 
   } 
   private static void getThreadReplies(String forumName, String threadSubject) {  
      Table table = dynamoDB.getTable(tableName);  
      String replyId = forumName + "#" + threadSubject; 
      QuerySpec spec = new QuerySpec() 
         .withKeyConditionExpression("Id = :v_id") 
         .withValueMap(new ValueMap() 
         .withString(":v_id", replyId)); 
         
      ItemCollection<QueryOutcome> items = table.query(spec); 
      System.out.println("\ngetThreadReplies results:"); 
      Iterator<Item> iterator = items.iterator(); 
      
      while (iterator.hasNext()) { 
         System.out.println(iterator.next().toJSONPretty()); 
      } 
   } 
}

As operações de varredura lêem todos os itens da tabela ou índices secundários. Sua função padrão resulta no retorno de todos os atributos de dados de todos os itens em um índice ou tabela. Empregue oProjectionExpression parâmetro em atributos de filtragem.

Cada varredura retorna um conjunto de resultados, mesmo sem encontrar correspondências, o que resulta em um conjunto vazio. As varreduras não recuperam mais do que 1 MB, com a opção de filtrar dados.

Note - Os parâmetros e a filtragem das verificações também se aplicam à consulta.

Tipos de operações de varredura

Filtering- As operações de varredura oferecem filtragem fina por meio de expressões de filtro, que modificam os dados após varreduras ou consultas; antes de retornar resultados. As expressões usam operadores de comparação. Sua sintaxe se assemelha a expressões de condição com exceção de atributos-chave, que as expressões de filtro não permitem. Você não pode usar uma partição ou chave de classificação em uma expressão de filtro.

Note - O limite de 1 MB se aplica antes de qualquer aplicação de filtragem.

Throughput Specifications- As varreduras consomem a taxa de transferência, no entanto, o consumo se concentra no tamanho do item em vez dos dados retornados. O consumo permanece o mesmo, quer você solicite todos os atributos ou apenas alguns, e o uso ou não de uma expressão de filtro também não afeta o consumo.

Pagination- O DynamoDB pagina os resultados, causando a divisão dos resultados em páginas específicas. O limite de 1 MB se aplica aos resultados retornados e, quando você o excede, outra varredura se torna necessária para reunir o restante dos dados. oLastEvaluatedKeyvalor permite que você execute esta varredura subsequente. Basta aplicar o valor aoExclusiveStartkey. Quando oLastEvaluatedKeyvalor torna-se nulo, a operação concluiu todas as páginas de dados. No entanto, um valor não nulo não significa automaticamente que mais dados permanecem. Apenas um valor nulo indica status.

The Limit Parameter- O parâmetro limite gerencia o tamanho do resultado. O DynamoDB o usa para estabelecer o número de itens a serem processados ​​antes de retornar os dados e não funciona fora do escopo. Se você definir um valor de x, o DynamoDB retornará os primeiros x itens correspondentes.

O valor LastEvaluatedKey também se aplica em casos de parâmetros de limite que produzem resultados parciais. Use-o para concluir varreduras.

Result Count - Respostas a consultas e varreduras também incluem informações relacionadas a ScannedCounte Contagem, que quantifica os itens lidos / consultados e quantifica os itens devolvidos. Se você não filtrar, seus valores serão idênticos. Quando você ultrapassa 1 MB, a contagem representa apenas a parte processada.

Consistency- Os resultados da consulta e da varredura são leituras eventualmente consistentes; no entanto, você também pode definir leituras fortemente consistentes. Use oConsistentRead parâmetro para alterar esta configuração.

Note - As configurações de leitura consistentes afetam o consumo, usando o dobro das unidades de capacidade quando definidas como fortemente consistentes.

Performance- As consultas oferecem melhor desempenho do que as varreduras devido às varreduras que rastreiam a tabela inteira ou o índice secundário, resultando em uma resposta lenta e alto consumo de rendimento. As varreduras funcionam melhor para tabelas pequenas e pesquisas com menos filtros; no entanto, você pode projetar varreduras enxutas obedecendo a algumas práticas recomendadas, como evitar atividade de leitura acelerada repentina e explorar varreduras paralelas.

Uma consulta encontra um certo intervalo de chaves que satisfazem uma determinada condição, com desempenho ditado pela quantidade de dados que recupera, e não pelo volume de chaves. Os parâmetros da operação e o número de correspondências afetam especificamente o desempenho.

Varredura paralela

As operações de digitalização executam o processamento sequencialmente por padrão. Em seguida, eles retornam dados em porções de 1 MB, o que faz com que o aplicativo busque a próxima porção. Isso resulta em longas varreduras de tabelas e índices grandes.

Essa característica também significa que as varreduras nem sempre podem explorar totalmente a taxa de transferência disponível. O DynamoDB distribui os dados da tabela em várias partições; e a taxa de transferência da varredura permanece limitada a uma única partição devido à sua operação de partição única.

Uma solução para esse problema vem da divisão lógica de tabelas ou índices em segmentos. Em seguida, os “trabalhadores” fazem a varredura paralela (simultaneamente) dos segmentos. Ele usa os parâmetros de segmento eTotalSegments para especificar segmentos verificados por certos trabalhadores e especificar a quantidade total de segmentos processados.

Número do Trabalhador

Você deve experimentar os valores do trabalhador (parâmetro Segment) para obter o melhor desempenho do aplicativo.

Note- Varreduras paralelas com grandes conjuntos de funcionários afetam o rendimento, possivelmente consumindo todo o rendimento. Gerencie esse problema com o parâmetro Limit, que você pode usar para impedir que um único trabalhador consuma todo o rendimento.

A seguir está um exemplo de varredura profunda.

Note- O programa a seguir pode assumir uma fonte de dados criada anteriormente. Antes de tentar executar, adquira bibliotecas de suporte e crie as fontes de dados necessárias (tabelas com as características necessárias ou outras fontes referenciadas).

Este exemplo também usa Eclipse IDE, um arquivo de credenciais AWS e o AWS Toolkit em um projeto Eclipse AWS Java.

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.ScanOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;

public class ScanOpSample {  
   static DynamoDB dynamoDB = new DynamoDB(
      new AmazonDynamoDBClient(new ProfileCredentialsProvider())); 
   static String tableName = "ProductList";  
   
   public static void main(String[] args) throws Exception { 
      findProductsUnderOneHun();                       //finds products under 100 dollars
   }  
   private static void findProductsUnderOneHun() { 
      Table table = dynamoDB.getTable(tableName);
      Map<String, Object> expressionAttributeValues = new HashMap<String, Object>(); 
      expressionAttributeValues.put(":pr", 100); 
         
      ItemCollection<ScanOutcome> items = table.scan ( 
         "Price < :pr",                                  //FilterExpression 
         "ID, Nomenclature, ProductCategory, Price",     //ProjectionExpression 
         null,                                           //No ExpressionAttributeNames  
         expressionAttributeValues);
         
      System.out.println("Scanned " + tableName + " to find items under $100."); 
      Iterator<Item> iterator = items.iterator(); 
         
      while (iterator.hasNext()) { 
         System.out.println(iterator.next().toJSONPretty()); 
      }     
   } 
}

O DynamoDB usa índices para atributos de chave primária para melhorar os acessos. Eles aceleram os acessos aos aplicativos e a recuperação de dados e oferecem um melhor desempenho ao reduzir o atraso do aplicativo.

Índice Secundário

Um índice secundário contém um subconjunto de atributos e uma chave alternativa. Você o usa por meio de uma consulta ou operação de varredura, que visa o índice.

Seu conteúdo inclui atributos que você projeta ou copia. Na criação, você define uma chave alternativa para o índice e todos os atributos que deseja projetar no índice. O DynamoDB então executa uma cópia dos atributos no índice, incluindo atributos de chave primária originados da tabela. Depois de realizar essas tarefas, você simplesmente usa uma consulta / varredura como se estivesse executando em uma mesa.

O DynamoDB mantém automaticamente todos os índices secundários. Em operações de item, como adição ou exclusão, ele atualiza todos os índices na tabela de destino.

O DynamoDB oferece dois tipos de índices secundários -

  • Global Secondary Index- Este índice inclui uma chave de partição e uma chave de classificação, que pode ser diferente da tabela de origem. Ele usa o rótulo “global” devido à capacidade de consultas / varreduras no índice para abranger todos os dados da tabela e em todas as partições.

  • Local Secondary Index- Este índice compartilha uma chave de partição com a tabela, mas usa uma chave de classificação diferente. Sua natureza “local” resulta do escopo de todas as suas partições para uma partição de tabela com valor de chave de partição idêntico.

O melhor tipo de índice a ser usado depende das necessidades do aplicativo. Considere as diferenças entre os dois apresentados na tabela a seguir -

Qualidade Índice Secundário Global Índice Secundário Local
Esquema de Chave Ele usa uma chave primária simples ou composta. Ele sempre usa uma chave primária composta.
Chaves de atributo A chave de partição do índice e a chave de classificação podem consistir em string, número ou atributos de tabela binários. A chave de partição do índice é um atributo compartilhado com a chave de partição da tabela. A chave de classificação pode ser string, número ou atributos de tabela binários.
Limites de tamanho por valor da chave de partição Eles não têm limitações de tamanho. Ele impõe um limite máximo de 10 GB no tamanho total dos itens indexados associados a um valor de chave de partição.
Operações de índice online Você pode gerá-los na criação da tabela, adicioná-los a tabelas existentes ou excluir as existentes. Você deve criá-los na criação da tabela, mas não pode excluí-los ou adicioná-los a tabelas existentes.
Consultas Ele permite consultas cobrindo toda a tabela e todas as partições. Eles tratam de partições únicas por meio do valor da chave de partição fornecido na consulta.
Consistência As consultas a esses índices oferecem apenas a opção eventualmente consistente. Consultas desses oferecem as opções de consistência eventual ou consistência forte.
Custo de transferência Inclui configurações de taxa de transferência para leituras e gravações. Consultas / varreduras consomem capacidade do índice, não da tabela, o que também se aplica a atualizações de gravação de tabela. Consultas / varreduras consomem capacidade de leitura da tabela. A tabela grava índices locais de atualização e consome unidades de capacidade da tabela.
Projeção Consultas / varreduras podem solicitar apenas atributos projetados no índice, sem recuperação de atributos da tabela. Consultas / varreduras podem solicitar aqueles atributos não projetados; além disso, ocorrem buscas automáticas deles.

Ao criar várias tabelas com índices secundários, faça isso sequencialmente; o que significa fazer uma mesa e esperar que ela atinja o estado ATIVO antes de criar outra e esperar novamente. O DynamoDB não permite a criação simultânea.

Cada índice secundário requer certas especificações -

  • Type - Especifique local ou global.

  • Name - Usa regras de nomenclatura idênticas às tabelas.

  • Key Schema - Somente string de nível superior, número ou tipo binário são permitidos, com o tipo de índice determinando outros requisitos.

  • Attributes for Projection - O DynamoDB os projeta automaticamente e permite qualquer tipo de dados.

  • Throughput - Especifique a capacidade de leitura / gravação para índices secundários globais.

O limite para índices permanece 5 globais e 5 locais por tabela.

Você pode acessar as informações detalhadas sobre os índices com DescribeTable. Ele retorna o nome, o tamanho e a contagem de itens.

Note - Esses valores são atualizados a cada 6 horas.

Em consultas ou varreduras usadas para acessar dados de índice, forneça os nomes da tabela e do índice, os atributos desejados para o resultado e quaisquer instruções condicionais. O DynamoDB oferece a opção de retornar os resultados em ordem crescente ou decrescente.

Note - A exclusão de uma tabela também exclui todos os índices.

Os aplicativos que requerem vários tipos de consulta com atributos diferentes podem usar um único ou vários índices secundários globais na execução dessas consultas detalhadas.

For example - Um sistema que mantém um registro dos usuários, seu status de login e o tempo de login. O crescimento do exemplo anterior retarda as consultas em seus dados.

Os índices secundários globais aceleram as consultas organizando uma seleção de atributos de uma tabela. Eles empregam chaves primárias na classificação de dados e não requerem atributos de tabela-chave ou esquema de chave idêntico ao da tabela.

Todos os índices secundários globais devem incluir uma chave de partição, com a opção de uma chave de classificação. O esquema da chave do índice pode ser diferente da tabela e os atributos da chave do índice podem usar qualquer string de nível superior, número ou atributos de tabela binários.

Em uma projeção, você pode usar outros atributos de tabela, no entanto, as consultas não são recuperadas das tabelas pai.

Projeções de Atributos

As projeções consistem em um conjunto de atributos copiado da tabela para o índice secundário. Uma projeção sempre ocorre com a chave de partição da tabela e a chave de classificação. Em consultas, as projeções permitem que o DynamoDB acesse qualquer atributo da projeção; eles existem essencialmente como sua própria mesa.

Em uma criação de índice secundário, você deve especificar atributos para projeção. O DynamoDB oferece três maneiras de realizar essa tarefa -

  • KEYS_ONLY- Todos os itens de índice consistem em partição de tabela e valores de chave de classificação e valores de chave de índice. Isso cria o menor índice.

  • INCLUDE - Inclui atributos KEYS_ONLY e atributos não chave especificados.

  • ALL - Inclui todos os atributos da tabela de origem, criando o maior índice possível.

Observe as vantagens e desvantagens de projetar atributos em um índice secundário global, que se relaciona ao rendimento e ao custo de armazenamento.

Considere os seguintes pontos -

  • Se você só precisa acessar alguns atributos, com baixa latência, projete apenas aqueles que você precisa. Isso reduz os custos de armazenamento e gravação.

  • Se um aplicativo acessa com frequência certos atributos não-chave, projete-os porque os custos de armazenamento diminuem em comparação ao consumo de digitalização.

  • Você pode projetar grandes conjuntos de atributos acessados ​​com frequência, no entanto, isso acarreta um alto custo de armazenamento.

  • Use KEYS_ONLY para consultas de tabela não frequentes e gravações / atualizações frequentes. Isso controla o tamanho, mas ainda oferece um bom desempenho nas consultas.

Consultas e varreduras de índice secundário global

Você pode utilizar consultas para acessar um único ou vários itens em um índice. Você deve especificar o índice e o nome da tabela, os atributos desejados e as condições; com a opção de retornar resultados em ordem crescente ou decrescente.

Você também pode utilizar varreduras para obter todos os dados de índice. Requer um nome de tabela e índice. Você utiliza uma expressão de filtro para recuperar dados específicos.

Sincronização de dados de tabela e índice

O DynamoDB executa automaticamente a sincronização dos índices com sua tabela pai. Cada operação de modificação em itens causa atualizações assíncronas; no entanto, os aplicativos não gravam nos índices diretamente.

Você precisa entender o impacto da manutenção do DynamoDB nos índices. Na criação de um índice, você especifica atributos-chave e tipos de dados, o que significa que em uma gravação, esses tipos de dados devem corresponder aos tipos de dados do esquema-chave.

Na criação ou exclusão do item, os índices são atualizados de maneira eventualmente consistente; no entanto, as atualizações dos dados se propagam em uma fração de segundo (a menos que ocorra algum tipo de falha no sistema). Você deve levar em consideração esse atraso nas inscrições.

Throughput Considerations in Global Secondary Indexes- Vários índices secundários globais afetam a taxa de transferência. A criação de índice requer especificações de unidade de capacidade, que existem separadas da tabela, resultando em operações que consomem unidades de capacidade de índice em vez de unidades de tabela.

Isso pode resultar em limitação se uma consulta ou gravação exceder a taxa de transferência provisionada. Visualize as configurações de taxa de transferência usandoDescribeTable.

Read Capacity- Os índices secundários globais fornecem consistência eventual. Em consultas, o DynamoDB executa cálculos de provisão idênticos aos usados ​​para tabelas, com a única diferença de usar o tamanho da entrada do índice em vez do tamanho do item. O limite de retornos de uma consulta permanece 1 MB, o que inclui o tamanho do nome do atributo e os valores em cada item retornado.

Capacidade de gravação

Quando ocorrem operações de gravação, o índice afetado consome unidades de gravação. Os custos de transferência de gravação são a soma das unidades de capacidade de gravação consumidas em gravações de tabela e unidades consumidas em atualizações de índice. Uma operação de gravação bem-sucedida requer capacidade suficiente ou resulta em limitação.

Os custos de gravação também dependem de certos fatores, alguns dos quais são os seguintes -

  • Novos itens que definem atributos indexados ou atualizações de itens que definem atributos indexados indefinidos usam uma única operação de gravação para adicionar o item ao índice.

  • As atualizações que alteram o valor do atributo de chave indexado usam duas gravações para excluir um item e gravar um novo.

  • Uma gravação de tabela que dispara a exclusão de um atributo indexado usa uma única gravação para apagar a projeção do item antigo no índice.

  • Os itens ausentes no índice antes e depois de uma operação de atualização não usam gravações.

  • As atualizações que mudam apenas o valor do atributo projetado no esquema da chave do índice, e não o valor do atributo da chave indexado, usam uma gravação para atualizar os valores dos atributos projetados no índice.

Todos esses fatores pressupõem um tamanho de item menor ou igual a 1 KB.

Armazenamento de índice secundário global

Na gravação de um item, o DynamoDB copia automaticamente o conjunto correto de atributos para quaisquer índices onde os atributos devam existir. Isso afeta sua conta, cobrando pelo armazenamento de itens de mesa e armazenamento de atributos. O espaço utilizado resulta da soma dessas quantidades -

  • Tamanho do byte da chave primária da tabela
  • Tamanho do byte do atributo da chave do índice
  • Tamanho de byte dos atributos projetados
  • 100 byte-overhead por item de índice

Você pode estimar as necessidades de armazenamento estimando o tamanho médio do item e multiplicando pela quantidade dos itens da tabela com os atributos-chave do índice secundário global.

O DynamoDB não grava dados de item para um item de tabela com um atributo indefinido definido como uma partição de índice ou chave de classificação.

Índice Secundário Global Bruto

Crie uma tabela com índices secundários globais usando o CreateTable operação emparelhada com o GlobalSecondaryIndexesparâmetro. Você deve especificar um atributo para servir como a chave de partição do índice ou usar outro para a chave de classificação do índice. Todos os atributos da chave do índice devem ser string, número ou escalares binários. Você também deve fornecer configurações de taxa de transferência, consistindo emReadCapacityUnits e WriteCapacityUnits.

Usar UpdateTable para adicionar índices secundários globais às tabelas existentes usando o parâmetro GlobalSecondaryIndexes mais uma vez.

Nesta operação, você deve fornecer as seguintes entradas -

  • Nome do índice
  • Esquema de chave
  • Atributos projetados
  • Configurações de rendimento

Ao adicionar um índice secundário global, pode levar um tempo substancial com grandes tabelas devido ao volume de itens, volume de atributos projetados, capacidade de gravação e atividade de gravação. UsarCloudWatch métricas para monitorar o processo.

Usar DescribeTablepara buscar informações de status para um índice secundário global. Ele retorna um de quatroIndexStatus para GlobalSecondaryIndexes -

  • CREATING - Indica o estágio de construção do índice e sua indisponibilidade.

  • ACTIVE - Indica a prontidão do índice para uso.

  • UPDATING - Indica o status de atualização das configurações de rendimento.

  • DELETING - Indica o status de exclusão do índice e sua indisponibilidade permanente para uso.

Atualize as configurações de rendimento provisionado do índice secundário global durante o estágio de carregamento / preenchimento (atributos de gravação do DynamoDB em um índice e rastreamento de itens adicionados / excluídos / atualizados). UsarUpdateTable para realizar esta operação.

Você deve se lembrar de que não pode adicionar / excluir outros índices durante o estágio de preenchimento.

Use UpdateTable para excluir índices secundários globais. Ele permite a exclusão de apenas um índice por operação, no entanto, você pode executar várias operações simultaneamente, até cinco. O processo de exclusão não afeta as atividades de leitura / gravação da tabela pai, mas você não pode adicionar / excluir outros índices até que a operação seja concluída.

Usando Java para trabalhar com índices secundários globais

Crie uma tabela com um índice por meio de CreateTable. Basta criar uma instância de classe DynamoDB, umCreateTableRequest instância de classe para solicitar informações e passar o objeto de solicitação para o método CreateTable.

O programa a seguir é um pequeno exemplo -

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient ( 
   new ProfileCredentialsProvider()));
   
// Attributes 
ArrayList<AttributeDefinition> attributeDefinitions = new 
   ArrayList<AttributeDefinition>();  
attributeDefinitions.add(new AttributeDefinition() 
   .withAttributeName("City") 
   .withAttributeType("S"));
   
attributeDefinitions.add(new AttributeDefinition() 
   .withAttributeName("Date") 
   .withAttributeType("S"));
   
attributeDefinitions.add(new AttributeDefinition() 
   .withAttributeName("Wind") 
   .withAttributeType("N"));
   
// Key schema of the table 
ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>(); 
tableKeySchema.add(new KeySchemaElement()
   .withAttributeName("City") 
   .withKeyType(KeyType.HASH));              //Partition key
   
tableKeySchema.add(new KeySchemaElement() 
   .withAttributeName("Date") 
   .withKeyType(KeyType.RANGE));             //Sort key
   
// Wind index 
GlobalSecondaryIndex windIndex = new GlobalSecondaryIndex() 
   .withIndexName("WindIndex") 
   .withProvisionedThroughput(new ProvisionedThroughput() 
   .withReadCapacityUnits((long) 10) 
   .withWriteCapacityUnits((long) 1)) 
   .withProjection(new Projection().withProjectionType(ProjectionType.ALL));
   
ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>(); 
indexKeySchema.add(new KeySchemaElement() 
   .withAttributeName("Date") 
   .withKeyType(KeyType.HASH));              //Partition key
   
indexKeySchema.add(new KeySchemaElement() 
   .withAttributeName("Wind") 
   .withKeyType(KeyType.RANGE));             //Sort key
   
windIndex.setKeySchema(indexKeySchema);  
CreateTableRequest createTableRequest = new CreateTableRequest() 
   .withTableName("ClimateInfo") 
   .withProvisionedThroughput(new ProvisionedThroughput() 
   .withReadCapacityUnits((long) 5) 
   .withWriteCapacityUnits((long) 1))
   .withAttributeDefinitions(attributeDefinitions) 
   .withKeySchema(tableKeySchema) 
   .withGlobalSecondaryIndexes(windIndex); 
Table table = dynamoDB.createTable(createTableRequest); 
System.out.println(table.getDescription());

Recupere as informações do índice com DescribeTable. Primeiro, crie uma instância de classe DynamoDB. Em seguida, crie uma instância da classe Table para direcionar um índice. Finalmente, passe a tabela para o método de descrição.

Aqui está um pequeno exemplo -

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient ( 
   new ProfileCredentialsProvider()));
   
Table table = dynamoDB.getTable("ClimateInfo"); 
TableDescription tableDesc = table.describe();  
Iterator<GlobalSecondaryIndexDescription> gsiIter = 
   tableDesc.getGlobalSecondaryIndexes().iterator(); 

while (gsiIter.hasNext()) { 
   GlobalSecondaryIndexDescription gsiDesc = gsiIter.next(); 
   System.out.println("Index data " + gsiDesc.getIndexName() + ":");  
   Iterator<KeySchemaElement> kse7Iter = gsiDesc.getKeySchema().iterator(); 
   
   while (kseIter.hasNext()) { 
      KeySchemaElement kse = kseIter.next(); 
      System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType()); 
   }
   Projection projection = gsiDesc.getProjection(); 
   System.out.println("\tProjection type: " + projection.getProjectionType()); 
   
   if (projection.getProjectionType().toString().equals("INCLUDE")) { 
      System.out.println("\t\tNon-key projected attributes: " 
         + projection.getNonKeyAttributes()); 
   } 
}

Use Query para realizar uma consulta de índice como uma consulta de tabela. Simplesmente crie uma instância de classe DynamoDB, uma instância de classe Table para o índice de destino, uma instância de classe Index para o índice específico e passe o índice e o objeto de consulta para o método de consulta.

Dê uma olhada no código a seguir para entender melhor -

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient ( 
   new ProfileCredentialsProvider()));
   
Table table = dynamoDB.getTable("ClimateInfo"); 
Index index = table.getIndex("WindIndex");  
QuerySpec spec = new QuerySpec() 
   .withKeyConditionExpression("#d = :v_date and Wind = :v_wind") 
   .withNameMap(new NameMap() 
   .with("#d", "Date"))
   .withValueMap(new ValueMap() 
   .withString(":v_date","2016-05-15") 
   .withNumber(":v_wind",0));
   
ItemCollection<QueryOutcome> items = index.query(spec);
Iterator<Item> iter = items.iterator();

while (iter.hasNext()) {
   System.out.println(iter.next().toJSONPretty()); 
}

O programa a seguir é um exemplo maior para melhor compreensão -

Note- O programa a seguir pode assumir uma fonte de dados criada anteriormente. Antes de tentar executar, adquira bibliotecas de suporte e crie as fontes de dados necessárias (tabelas com as características necessárias ou outras fontes referenciadas).

Este exemplo também usa Eclipse IDE, um arquivo de credenciais AWS e o AWS Toolkit em um projeto Eclipse AWS Java.

import java.util.ArrayList;
import java.util.Iterator;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Index;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;

import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.Projection;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;

public class GlobalSecondaryIndexSample {  
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient ( 
      new ProfileCredentialsProvider()));  
   public static String tableName = "Bugs";   
   public static void main(String[] args) throws Exception {  
      createTable(); 
      queryIndex("CreationDateIndex"); 
      queryIndex("NameIndex"); 
      queryIndex("DueDateIndex"); 
   }
   public static void createTable() {  
      // Attributes 
      ArrayList<AttributeDefinition> attributeDefinitions = new 
         ArrayList<AttributeDefinition>();  
      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("BugID") 
         .withAttributeType("S")); 
         
      attributeDefinitions.add(new AttributeDefinition() 
         .withAttributeName("Name")
         .withAttributeType("S"));
         
      attributeDefinitions.add(new AttributeDefinition() 
         .withAttributeName("CreationDate")
         .withAttributeType("S"));
         
      attributeDefinitions.add(new AttributeDefinition() 
         .withAttributeName("DueDate") 
         .withAttributeType("S"));
         
      // Table Key schema
      ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>(); 
      tableKeySchema.add (new KeySchemaElement() 
         .withAttributeName("BugID") 
         .withKeyType(KeyType.HASH));              //Partition key 
      
      tableKeySchema.add (new KeySchemaElement() 
         .withAttributeName("Name") 
         .withKeyType(KeyType.RANGE));             //Sort key
         
      // Indexes' initial provisioned throughput
      ProvisionedThroughput ptIndex = new ProvisionedThroughput()
         .withReadCapacityUnits(1L)
         .withWriteCapacityUnits(1L);
         
      // CreationDateIndex 
      GlobalSecondaryIndex creationDateIndex = new GlobalSecondaryIndex() 
         .withIndexName("CreationDateIndex") 
         .withProvisionedThroughput(ptIndex) 
         .withKeySchema(new KeySchemaElement() 
         .withAttributeName("CreationDate") 
         .withKeyType(KeyType.HASH),               //Partition key 
         new KeySchemaElement()
         .withAttributeName("BugID") 
         .withKeyType(KeyType.RANGE))              //Sort key 
         .withProjection(new Projection() 
         .withProjectionType("INCLUDE") 
         .withNonKeyAttributes("Description", "Status"));
         
      // NameIndex 
      GlobalSecondaryIndex nameIndex = new GlobalSecondaryIndex() 
         .withIndexName("NameIndex") 
         .withProvisionedThroughput(ptIndex) 
         .withKeySchema(new KeySchemaElement()  
         .withAttributeName("Name")  
         .withKeyType(KeyType.HASH),                  //Partition key 
         new KeySchemaElement()  
         .withAttributeName("BugID")  
         .withKeyType(KeyType.RANGE))                 //Sort key 
         .withProjection(new Projection() 
         .withProjectionType("KEYS_ONLY"));
         
      // DueDateIndex 
      GlobalSecondaryIndex dueDateIndex = new GlobalSecondaryIndex() 
         .withIndexName("DueDateIndex") 
         .withProvisionedThroughput(ptIndex) 
         .withKeySchema(new KeySchemaElement() 
         .withAttributeName("DueDate") 
         .withKeyType(KeyType.HASH))               //Partition key 
         .withProjection(new Projection() 
         .withProjectionType("ALL"));
         
      CreateTableRequest createTableRequest = new CreateTableRequest() 
         .withTableName(tableName) 
         .withProvisionedThroughput( new ProvisionedThroughput() 
         .withReadCapacityUnits( (long) 1) 
         .withWriteCapacityUnits( (long) 1)) 
         .withAttributeDefinitions(attributeDefinitions)
         .withKeySchema(tableKeySchema)
         .withGlobalSecondaryIndexes(creationDateIndex, nameIndex, dueDateIndex);  
         System.out.println("Creating " + tableName + "..."); 
         dynamoDB.createTable(createTableRequest);  
      
      // Pause for active table state 
      System.out.println("Waiting for ACTIVE state of " + tableName); 
      try { 
         Table table = dynamoDB.getTable(tableName); 
         table.waitForActive(); 
      } catch (InterruptedException e) { 
         e.printStackTrace(); 
      } 
   }
   public static void queryIndex(String indexName) { 
      Table table = dynamoDB.getTable(tableName);  
      System.out.println 
      ("\n*****************************************************\n"); 
      System.out.print("Querying index " + indexName + "...");  
      Index index = table.getIndex(indexName);  
      ItemCollection<QueryOutcome> items = null; 
      QuerySpec querySpec = new QuerySpec();  
      
      if (indexName == "CreationDateIndex") { 
         System.out.println("Issues filed on 2016-05-22"); 
         querySpec.withKeyConditionExpression("CreationDate = :v_date and begins_with
            (BugID, :v_bug)") 
            .withValueMap(new ValueMap() 
            .withString(":v_date","2016-05-22")
            .withString(":v_bug","A-")); 
         items = index.query(querySpec); 
      } else if (indexName == "NameIndex") { 
         System.out.println("Compile error"); 
         querySpec.withKeyConditionExpression("Name = :v_name and begins_with
            (BugID, :v_bug)") 
            .withValueMap(new ValueMap() 
            .withString(":v_name","Compile error") 
            .withString(":v_bug","A-")); 
         items = index.query(querySpec); 
      } else if (indexName == "DueDateIndex") { 
         System.out.println("Items due on 2016-10-15"); 
         querySpec.withKeyConditionExpression("DueDate = :v_date") 
         .withValueMap(new ValueMap() 
         .withString(":v_date","2016-10-15")); 
         items = index.query(querySpec); 
      } else { 
         System.out.println("\nInvalid index name"); 
         return; 
      }  
      Iterator<Item> iterator = items.iterator(); 
      System.out.println("Query: getting result..."); 
      
      while (iterator.hasNext()) { 
         System.out.println(iterator.next().toJSONPretty()); 
      } 
   } 
}

Alguns aplicativos realizam consultas apenas com a chave primária, mas algumas situações se beneficiam de uma chave de classificação alternativa. Permita que seu aplicativo escolha criando um ou vários índices secundários locais.

Requisitos complexos de acesso a dados, como combinar milhões de itens, tornam necessário realizar consultas / varreduras mais eficientes. Os índices secundários locais fornecem uma chave de classificação alternativa para um valor de chave de partição. Eles também mantêm cópias de todos ou alguns atributos da tabela. Eles organizam os dados por chave de partição de tabela, mas usam uma chave de classificação diferente.

Usar um índice secundário local elimina a necessidade de uma varredura de tabela inteira e permite uma consulta simples e rápida usando uma chave de classificação.

Todos os índices secundários locais devem satisfazer certas condições -

  • Chave de partição idêntica e chave de partição da tabela de origem.
  • Uma chave de classificação de apenas um atributo escalar.
  • Projeção da chave de classificação da tabela de origem atuando como um atributo não chave.

Todos os índices secundários locais mantêm automaticamente as chaves de partição e classificação das tabelas pai. Em consultas, isso significa coleta eficiente de atributos projetados e também recuperação de atributos não projetados.

O limite de armazenamento para um índice secundário local permanece 10 GB por valor de chave de partição, que inclui todos os itens de tabela e itens de índice que compartilham um valor de chave de partição.

Projetando um Atributo

Algumas operações exigem leituras / buscas em excesso devido à complexidade. Essas operações podem consumir uma taxa de transferência substancial. A projeção permite evitar buscas caras e realizar consultas valiosas, isolando esses atributos. Lembre-se de que as projeções consistem em atributos copiados em um índice secundário.

Ao fazer um índice secundário, você especifica os atributos projetados. Lembre-se das três opções fornecidas pelo DynamoDB:KEYS_ONLY, INCLUDE, and ALL.

Ao optar por certos atributos na projeção, considere as compensações de custo associadas -

  • Se você projetar apenas um pequeno conjunto de atributos necessários, reduzirá drasticamente os custos de armazenamento.

  • Se você projeta atributos não essenciais acessados ​​com frequência, compensa os custos de digitalização com os custos de armazenamento.

  • Se você projetar a maioria ou todos os atributos não-chave, isso maximiza a flexibilidade e reduz o rendimento (sem recuperações); no entanto, os custos de armazenamento aumentam.

  • Se você projetar KEYS_ONLY para gravações / atualizações frequentes e consultas não frequentes, ele minimiza o tamanho, mas mantém a preparação da consulta.

Criação de índice secundário local

Use o LocalSecondaryIndexparâmetro de CreateTable para fazer um único ou vários índices secundários locais. Você deve especificar um atributo não chave para a chave de classificação. Na criação da tabela, você cria índices secundários locais. Na exclusão, você exclui esses índices.

As tabelas com um índice secundário local devem obedecer a um limite de 10 GB de tamanho por valor de chave de partição, mas podem armazenar qualquer quantidade de itens.

Consultas e varreduras de índice secundário local

Uma operação de consulta em índices secundários locais retorna todos os itens com um valor de chave de partição correspondente quando vários itens no índice compartilham valores de chave de classificação. Os itens correspondentes não retornam em uma determinada ordem. As consultas para índices secundários locais usam consistência eventual ou forte, com leituras consistentes fornecendo os valores mais recentes.

Uma operação de varredura retorna todos os dados de índice secundário local. As varreduras exigem que você forneça um nome de tabela e índice e permita o uso de uma expressão de filtro para descartar dados.

Escrita de Item

Na criação de um índice secundário local, você especifica um atributo de chave de classificação e seu tipo de dados. Quando você escreve um item, seu tipo deve corresponder ao tipo de dados do esquema de chave se o item definir um atributo de uma chave de índice.

O DynamoDB não impõe requisitos de relacionamento um para um nos itens de tabela e itens de índice secundário local. As tabelas com vários índices secundários locais acarretam custos de gravação mais altos do que aquelas com menos.

Considerações de taxa de transferência em índices secundários locais

O consumo da capacidade de leitura de uma consulta depende da natureza do acesso aos dados. As consultas usam consistência eventual ou forte, com leituras fortemente consistentes usando uma unidade em comparação com a metade de uma unidade em leituras eventualmente consistentes.

As limitações de resultados incluem um tamanho máximo de 1 MB. Os tamanhos dos resultados vêm da soma do tamanho do item do índice correspondente arredondado para o 4KB mais próximo e o tamanho do item da tabela correspondente também arredondado para o 4KB mais próximo.

O consumo da capacidade de gravação permanece dentro das unidades provisionadas. Calcule o custo total provisionado encontrando a soma das unidades consumidas na escrita da tabela e das unidades consumidas nos índices de atualização.

Você também pode considerar os principais fatores que influenciam o custo, alguns dos quais podem ser -

  • Quando você escreve um item definindo um atributo indexado ou atualiza um item para definir um atributo indexado indefinido, ocorre uma única operação de gravação.

  • Quando uma atualização de tabela altera um valor de atributo de chave indexado, duas gravações ocorrem para excluir e então - adicionar um item.

  • Quando uma gravação causa a exclusão de um atributo indexado, ocorre uma gravação para remover a projeção do item antigo.

  • Quando um item não existe no índice antes ou depois de uma atualização, nenhuma gravação ocorre.

Armazenamento de índice secundário local

Em uma gravação de item de tabela, o DynamoDB copia automaticamente o conjunto de atributos correto para os índices secundários locais necessários. Isso cobra sua conta. O espaço usado resulta da soma do tamanho do byte da chave primária da tabela, tamanho do byte do atributo da chave do índice, qualquer tamanho do byte do atributo projetado presente e 100 bytes de sobrecarga para cada item do índice.

O armazenamento estimado é obtido estimando o tamanho médio do item do índice e multiplicando pela quantidade do item da tabela.

Usando Java para trabalhar com índices secundários locais

Crie um índice secundário local criando primeiro uma instância de classe DynamoDB. Em seguida, crie uma instância de classe CreateTableRequest com as informações de solicitação necessárias. Finalmente, use o método createTable.

Exemplo

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));
String tableName = "Tools";  
CreateTableRequest createTableRequest = new 
   CreateTableRequest().withTableName(tableName);
   
//Provisioned Throughput
createTableRequest.setProvisionedThroughput (
   new ProvisionedThroughput()
   .withReadCapacityUnits((long)5)
   .withWriteCapacityUnits(( long)5));
   
//Attributes 
ArrayList<AttributeDefinition> attributeDefinitions = 
   new ArrayList<AttributeDefinition>();
   attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Make")
   .withAttributeType("S"));
   
attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Model")
   .withAttributeType("S"));
   
attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Line")
   .withAttributeType("S"));
   
createTableRequest.setAttributeDefinitions(attributeDefinitions);

//Key Schema 
ArrayList<KeySchemaElement> tableKeySchema = new 
   ArrayList<KeySchemaElement>();
   
tableKeySchema.add(new KeySchemaElement()
   .withAttributeName("Make")
   .withKeyType(KeyType.HASH));                    //Partition key
   
tableKeySchema.add(new KeySchemaElement()
   .withAttributeName("Model")
   .withKeyType(KeyType.RANGE));                   //Sort key
   
createTableRequest.setKeySchema(tableKeySchema);
ArrayList<KeySchemaElement> indexKeySchema = new 
   ArrayList<KeySchemaElement>();
   
indexKeySchema.add(new KeySchemaElement()
   .withAttributeName("Make")
   .withKeyType(KeyType.HASH));                   //Partition key
   
indexKeySchema.add(new KeySchemaElement()
   .withAttributeName("Line")
   .withKeyType(KeyType.RANGE));                   //Sort key
   
Projection projection = new Projection()
   .withProjectionType(ProjectionType.INCLUDE);

ArrayList<String> nonKeyAttributes = new ArrayList<String>(); 
nonKeyAttributes.add("Type"); 
nonKeyAttributes.add("Year"); 
projection.setNonKeyAttributes(nonKeyAttributes);  

LocalSecondaryIndex localSecondaryIndex = new LocalSecondaryIndex() 
   .withIndexName("ModelIndex")
   .withKeySchema(indexKeySchema)
   .withProjection(p rojection);  

ArrayList<LocalSecondaryIndex> localSecondaryIndexes = new 
   ArrayList<LocalSecondaryIndex>(); 

localSecondaryIndexes.add(localSecondaryIndex); 
createTableRequest.setLocalSecondaryIndexes(localSecondaryIndexes);  
Table table = dynamoDB.createTable(createTableRequest); 
System.out.println(table.getDescription());

Recupere informações sobre um índice secundário local com o método describe. Simplesmente crie uma instância de classe DynamoDB, crie uma instância de classe Table e passe a tabela para o método describe.

Exemplo

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));
   
String tableName = "Tools";
Table table = dynamoDB.getTable(tableName);
TableDescription tableDescription = table.describe();

List<LocalSecondaryIndexDescription> localSecondaryIndexes = 
   tableDescription.getLocalSecondaryIndexes();
   
Iterator<LocalSecondaryIndexDescription> lsiIter = 
   localSecondaryIndexes.iterator();
   
while (lsiIter.hasNext()) {  
   LocalSecondaryIndexDescription lsiDescription = lsiIter.next(); 
   System.out.println("Index info " + lsiDescription.getIndexName() + ":"); 
   Iterator<KeySchemaElement> kseIter = lsiDescription.getKeySchema().iterator(); 
   
   while (kseIter.hasNext()) { 
      KeySchemaElement kse = kseIter.next(); 
      System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType()); 
   }
   
   Projection projection = lsiDescription.getProjection(); 
   System.out.println("\tProjection type: " + projection.getProjectionType()); 
   
   if (projection.getProjectionType().toString().equals("INCLUDE")) { 
      System.out.println("\t\tNon-key projected attributes: " + 
         projection.getNonKeyAttributes()); 
   } 
}

Execute uma consulta usando as mesmas etapas de uma consulta de tabela. Basta criar uma instância da classe DynamoDB, uma instância da classe Table, uma instância da classe Index, um objeto de consulta e utilizar o método de consulta.

Exemplo

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));
   
String tableName = "Tools";  
Table table = dynamoDB.getTable(tableName); 
Index index = table.getIndex("LineIndex");  
QuerySpec spec = new QuerySpec() 
   .withKeyConditionExpression("Make = :v_make and Line = :v_line") 
   .withValueMap(new ValueMap() 
   .withString(":v_make", "Depault") 
   .withString(":v_line", "SuperSawz"));
      
ItemCollection<QueryOutcome> items = index.query(spec);
Iterator<Item> itemsIter = items.iterator();

while (itemsIter.hasNext()) { 
   Item item = itemsIter.next(); 
   System.out.println(item.toJSONPretty()); 
}

Você também pode revisar o exemplo a seguir.

Note- O exemplo a seguir pode assumir uma fonte de dados criada anteriormente. Antes de tentar executar, adquira bibliotecas de suporte e crie as fontes de dados necessárias (tabelas com as características necessárias ou outras fontes referenciadas).

O exemplo a seguir também usa Eclipse IDE, um arquivo de credenciais AWS e o AWS Toolkit em um projeto Eclipse AWS Java.

Exemplo

import java.util.ArrayList;
import java.util.Iterator;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;

import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Index;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.PutItemOutcome;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;

import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.LocalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.Projection;
import com.amazonaws.services.dynamodbv2.model.ProjectionType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ReturnConsumedCapacity;
import com.amazonaws.services.dynamodbv2.model.Select;

public class LocalSecondaryIndexSample {  
   static DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
      new ProfileCredentialsProvider()));  
   public static String tableName = "ProductOrders";  
   
   public static void main(String[] args) throws Exception {  
      createTable();
      query(null); 
      query("IsOpenIndex"); 
      query("OrderCreationDateIndex"); 
   }
   public static void createTable() { 
      CreateTableRequest createTableRequest = new CreateTableRequest() 
         .withTableName(tableName) 
         .withProvisionedThroughput(new ProvisionedThroughput() 
         .withReadCapacityUnits((long) 1) 
         .withWriteCapacityUnits((long) 1));
         
      // Table partition and sort keys attributes 
      ArrayList<AttributeDefinition> attributeDefinitions = new 
         ArrayList<AttributeDefinition>(); 
      
      attributeDefinitions.add(new AttributeDefinition() 
         .withAttributeName("CustomerID") 
         .withAttributeType("S"));
         
      attributeDefinitions.add(new AttributeDefinition() 
         .withAttributeName("OrderID") 
         .withAttributeType("N"));
         
      // Index primary key attributes 
      attributeDefinitions.add(new AttributeDefinition() 
         .withAttributeName("OrderDate") 
         .withAttributeType("N"));
         
      attributeDefinitions.add(new AttributeDefinition() 
         .withAttributeName("OpenStatus") 
         .withAttributeType("N"));  
      createTableRequest.setAttributeDefinitions(attributeDefinitions);
      
      // Table key schema 
      ArrayList<KeySchemaElement> tableKeySchema = new
         ArrayList<KeySchemaElement>(); 
      tableKeySchema.add(new KeySchemaElement()  
         .withAttributeName("CustomerID") 
         .withKeyType(KeyType.HASH));                    //Partition key
         
      tableKeySchema.add(new KeySchemaElement() 
         .withAttributeName("OrderID") 
         .withKeyType(KeyType.RANGE));                   //Sort key
         
      createTableRequest.setKeySchema(tableKeySchema);  
      ArrayList<LocalSecondaryIndex> localSecondaryIndexes = new 
         ArrayList<LocalSecondaryIndex>();  
      
      // OrderDateIndex 
      LocalSecondaryIndex orderDateIndex = new LocalSecondaryIndex() 
         .withIndexName("OrderDateIndex");
         
      // OrderDateIndex key schema 
      ArrayList<KeySchemaElement> indexKeySchema = new 
         ArrayList<KeySchemaElement>(); 
      indexKeySchema.add(new KeySchemaElement() 
         .withAttributeName("CustomerID") 
         .withKeyType(KeyType.HASH));                   //Partition key
         
      indexKeySchema.add(new KeySchemaElement() 
         .withAttributeName("OrderDate") 
         .withKeyType(KeyType.RANGE));                   //Sort key
      orderDateIndex.setKeySchema(indexKeySchema);
      
      // OrderCreationDateIndex projection w/attributes list 
      Projection projection = new Projection() 
         .withProjectionType(ProjectionType.INCLUDE); 
      
      ArrayList<String> nonKeyAttributes = new ArrayList<String>(); 
      nonKeyAttributes.add("ProdCat"); 
      nonKeyAttributes.add("ProdNomenclature"); 
      projection.setNonKeyAttributes(nonKeyAttributes);
      orderCreationDateIndex.setProjection(projection);  
      localSecondaryIndexes.add(orderDateIndex);  
      
      // IsOpenIndex 
      LocalSecondaryIndex isOpenIndex = new LocalSecondaryIndex() 
         .withIndexName("IsOpenIndex");  
      
      // OpenStatusIndex key schema 
      indexKeySchema = new ArrayList<KeySchemaElement>(); 
      indexKeySchema.add(new KeySchemaElement() 
         .withAttributeName("CustomerID") 
         .withKeyType(KeyType.HASH));                   //Partition key
         
      indexKeySchema.add(new KeySchemaElement() 
         .withAttributeName("OpenStatus") 
         .withKeyType(KeyType.RANGE));                   //Sort key
         
      // OpenStatusIndex projection 
      projection = new Projection() .withProjectionType(ProjectionType.ALL);  
      OpenStatusIndex.setKeySchema(indexKeySchema); 
      OpenStatusIndex.setProjection(projection);  
      localSecondaryIndexes.add(OpenStatusIndex);  
      
      // Put definitions in CreateTable request 
      createTableRequest.setLocalSecondaryIndexes(localSecondaryIndexes);  
      System.out.println("Spawning table " + tableName + "..."); 
      System.out.println(dynamoDB.createTable(createTableRequest));  
      
      // Pause for ACTIVE status 
      System.out.println("Waiting for ACTIVE table:" + tableName); 
      try { 
         Table table = dynamoDB.getTable(tableName);
         table.waitForActive(); 
      } catch (InterruptedException e) { 
         e.printStackTrace(); 
      } 
   }
   public static void query(String indexName) {  
      Table table = dynamoDB.getTable(tableName);  
      System.out.println("\n*************************************************\n"); 
      System.out.println("Executing query on" + tableName);  
      QuerySpec querySpec = new QuerySpec() 
         .withConsistentRead(true) 
         .withScanIndexForward(true) 
         .withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);
      
      if (indexName == "OpenStatusIndex") {  
         System.out.println("\nEmploying index: '" + indexName 
            + "' open orders for this customer.");
            
         System.out.println( 
            "Returns only user-specified attribute list\n"); 
         Index index = table.getIndex(indexName); 
             
         querySpec.withKeyConditionExpression("CustomerID = :v_custmid and 
            OpenStatus = :v_openstat") 
            .withValueMap(new ValueMap() 
            .withString(":v_custmid", "[email protected]") 
            .withNumber(":v_openstat", 1));  
         
         querySpec.withProjectionExpression( 
            "OrderDate, ProdCat, ProdNomenclature, OrderStatus"); 
            ItemCollection<QueryOutcome> items = index.query(querySpec); 
            Iterator<Item> iterator = items.iterator();  
            System.out.println("Printing query results...");  
            
         while (iterator.hasNext()) { 
            System.out.println(iterator.next().toJSONPretty()); 
         }  
      } else if (indexName == "OrderDateIndex") { 
         System.out.println("\nUsing index: '" + indexName 
            + "': this customer's orders placed after 05/22/2016."); 
         System.out.println("Projected attributes are returned\n"); 
         Index index = table.getIndex(indexName); 
             
         querySpec.withKeyConditionExpression("CustomerID = :v_custmid and OrderDate 
            >= :v_ordrdate") 
            .withValueMap(new ValueMap() 
            .withString(":v_custmid", "[email protected]") 
            .withNumber(":v_ordrdate", 20160522));
               
         querySpec.withSelect(Select.ALL_PROJECTED_ATTRIBUTES);  
         ItemCollection<QueryOutcome> items = index.query(querySpec); 
         Iterator<Item> iterator = items.iterator();  
         System.out.println("Printing query results...");  
            
         while (iterator.hasNext()) { 
            System.out.println(iterator.next().toJSONPretty()); 
         }  
      } else { 
         System.out.println("\nNo index: All Jane's orders by OrderID:\n"); 
         querySpec.withKeyConditionExpression("CustomerID = :v_custmid") 
            .withValueMap(new ValueMap()
            .withString(":v_custmid", "[email protected]"));  
         
         ItemCollection<QueryOutcome> items = table.query(querySpec); 
         Iterator<Item> iterator = items.iterator();  
         System.out.println("Printing query results...");  
         
         while (iterator.hasNext()) { 
            System.out.println(iterator.next().toJSONPretty()); 
         } 
      } 
   } 
}

O DynamoDB não oferece funções de agregação. Você deve fazer uso criativo de consultas, varreduras, índices e ferramentas variadas para executar essas tarefas. Em tudo isso, a despesa de transferência de consultas / varreduras nessas operações pode ser pesada.

Você também tem a opção de usar bibliotecas e outras ferramentas para sua linguagem de codificação preferida do DynamoDB. Certifique-se de sua compatibilidade com o DynamoDB antes de usá-lo.

Calcular máximo ou mínimo

Utilize a ordem crescente / decrescente de armazenamento dos resultados, o parâmetro Limit e quaisquer parâmetros que definam a ordem para encontrar os valores mais altos e mais baixos.

Por exemplo -

Map<String, AttributeValue> eaval = new HashMap<>(); 
eaval.put(":v1", new AttributeValue().withS("hashval")); 
queryExpression = new DynamoDBQueryExpression<Table>() 
   .withIndexName("yourindexname") 
   .withKeyConditionExpression("HK = :v1") 
   .withExpressionAttributeValues(values) 
   .withScanIndexForward(false);                //descending order 

queryExpression.setLimit(1); 
QueryResultPage<Lookup> res = 
   dynamoDBMapper.queryPage(Table.class, queryExpression);

Calcular contagem

Usar DescribeTablepara obter uma contagem dos itens da tabela, no entanto, observe que ela fornece dados desatualizados. Além disso, utilize o JavagetScannedCount method.

Utilizar LastEvaluatedKey para garantir que fornece todos os resultados.

Por exemplo -

ScanRequest scanRequest = new ScanRequest().withTableName(yourtblName); 
ScanResult yourresult = client.scan(scanRequest); 
System.out.println("#items:" + yourresult.getScannedCount());

Calculando a média e a soma

Utilize índices e uma consulta / varredura para recuperar e filtrar valores antes do processamento. Em seguida, simplesmente opere esses valores por meio de um objeto.

O DynamoDB usa as credenciais fornecidas por você para autenticar solicitações. Essas credenciais são necessárias e devem incluir permissões para acesso a recursos da AWS. Essas permissões abrangem virtualmente todos os aspectos do DynamoDB até os menores recursos de uma operação ou funcionalidade.

Tipos de permissões

Nesta seção, discutiremos sobre as várias permissões e acesso a recursos no DynamoDB.

Autenticação de usuários

Na inscrição, você forneceu uma senha e um e-mail, que servem como credenciais de root. O DynamoDB associa esses dados à sua conta AWS e os usa para fornecer acesso completo a todos os recursos.

A AWS recomenda que você use suas credenciais raiz apenas para a criação de uma conta de administração. Isso permite que você crie contas / usuários IAM com menos privilégios. Os usuários IAM são outras contas geradas com o serviço IAM. Suas permissões / privilégios de acesso incluem acesso a páginas seguras e certas permissões personalizadas, como modificação de tabelas.

As chaves de acesso fornecem outra opção para contas e acesso adicionais. Use-os para conceder acesso e também para evitar a concessão manual de acesso em determinadas situações. Os usuários federados fornecem outra opção, permitindo o acesso por meio de um provedor de identidade.

Administração

Os recursos da AWS permanecem sob a propriedade de uma conta. As políticas de permissões regem as permissões concedidas para gerar ou acessar recursos. Os administradores associam políticas de permissões a identidades IAM, ou seja, funções, grupos, usuários e serviços. Eles também anexam permissões aos recursos.

As permissões especificam usuários, recursos e ações. Observe que os administradores são apenas contas com privilégios de administrador.

Operação e Recursos

As tabelas continuam sendo os principais recursos do DynamoDB. Os sub-recursos servem como recursos adicionais, por exemplo, fluxos e índices. Esses recursos usam nomes exclusivos, alguns dos quais são mencionados na tabela a seguir -

Tipo ARN (nome do recurso Amazon)
Corrente arn: aws: dynamodb: region: account-id: table / table-name / stream / stream-label
Índice arn: aws: dynamodb: region: account-id: table / table-name / index / index-name
Mesa arn: aws: dynamodb: region: account-id: table / table-name

Propriedade

Um proprietário de recurso é definido como uma conta da AWS que gerou o recurso, ou conta da entidade principal responsável por solicitar autenticação na criação de recursos. Considere como isso funciona dentro do ambiente DynamoDB -

  • Ao usar credenciais de root para criar uma tabela, sua conta continua sendo a proprietária do recurso.

  • Ao criar um usuário IAM e conceder a ele permissão para criar uma tabela, sua conta continua sendo a proprietária do recurso.

  • Ao criar um usuário IAM e conceder ao usuário, e a qualquer pessoa capaz de assumir a função, permissão para criar uma tabela, sua conta continua sendo a proprietária do recurso.

Gerenciar acesso a recursos

O gerenciamento de acesso requer principalmente atenção a uma política de permissões que descreve o acesso de usuários e recursos. Você associa políticas a identidades ou recursos do IAM. No entanto, o DynamoDB só oferece suporte a IAM / políticas de identidade.

As políticas baseadas em identidade (IAM) permitem que você conceda privilégios das seguintes maneiras -

  • Anexe permissões a usuários ou grupos.
  • Anexe permissões a funções para permissões entre contas.

Outros AWS permitem políticas baseadas em recursos. Essas políticas permitem acesso a coisas como um depósito S3.

Elementos de Política

As políticas definem ações, efeitos, recursos e princípios; e conceder permissão para realizar essas operações.

Note - As operações da API podem exigir permissões para várias ações.

Dê uma olhada nos seguintes elementos de política -

  • Resource - Um ARN identifica isso.

  • Action - Palavras-chave identificam essas operações de recursos e se devem ser permitidas ou negadas.

  • Effect - Especifica o efeito de uma solicitação de ação do usuário, o que significa permitir ou negar com negação como padrão.

  • Principal - Isso identifica o usuário anexado à política.

Condições

Ao conceder permissões, você pode especificar as condições para quando as políticas se tornam ativas, como em uma data específica. Condições expressas com chaves de condição, que incluem chaves do sistema AWS e chaves do DynamoDB. Essas chaves são discutidas em detalhes posteriormente no tutorial.

Permissões do console

Um usuário requer certas permissões básicas para usar o console. Eles também exigem permissões para o console em outros serviços padrão -

  • CloudWatch
  • Pipeline de dados
  • Gerenciamento de identidade e acesso
  • Serviço de Notificação
  • Lambda

Se a política do IAM for muito limitada, o usuário não poderá usar o console de maneira eficaz. Além disso, você não precisa se preocupar com as permissões do usuário para aqueles que apenas chamam a CLI ou API.

Políticas de uso comum do Iam

AWS cobre operações comuns em permissões com políticas gerenciadas IAM autônomas. Eles fornecem permissões importantes, permitindo que você evite investigações profundas sobre o que você deve conceder.

Alguns deles são os seguintes -

  • AmazonDynamoDBReadOnlyAccess - Dá acesso somente leitura por meio do console.

  • AmazonDynamoDBFullAccess - Dá acesso total via console.

  • AmazonDynamoDBFullAccesswithDataPipeline - Dá acesso total via console e permite exportação / importação com Data Pipeline.

Você também pode, claro, fazer políticas personalizadas.

Concessão de privilégios: usando o shell

Você pode conceder permissões com o shell Javascript. O programa a seguir mostra uma política de permissões típica -

{ 
   "Version": "2016-05-22", 
   "Statement": [ 
      { 
         "Sid": "DescribeQueryScanToolsTable", 
         "Effect": "Deny", 
         
         "Action": [ 
            "dynamodb:DescribeTable", 
            "dynamodb:Query", 
            "dynamodb:Scan" 
         ], 
         "Resource": "arn:aws:dynamodb:us-west-2:account-id:table/Tools" 
      } 
   ] 
}

Você pode revisar os três exemplos que são os seguintes -

Block the user from executing any table action.

{ 
   "Version": "2016-05-23", 
   "Statement": [ 
      { 
         "Sid": "AllAPIActionsOnTools", 
         "Effect": "Deny", 
         "Action": "dynamodb:*", 
         "Resource": "arn:aws:dynamodb:us-west-2:155556789012:table/Tools" 
      } 
   ] 
}

Block access to a table and its indices.

{ 
   "Version": "2016-05-23", 
   "Statement": [ 
      { 
         "Sid": "AccessAllIndexesOnTools", 
         "Effect": "Deny", 
         "Action": [
            "dynamodb:*" 
         ], 
         "Resource": [ 
            "arn:aws:dynamodb:us-west-2:155556789012:table/Tools", 
            "arn:aws:dynamodb:us-west-2:155556789012:table/Tools/index/*" 
         ] 
      } 
   ] 
}

Block a user from making a reserved capacity offering purchase.

{ 
   "Version": "2016-05-23", 
   "Statement": [ 
      { 
         "Sid": "BlockReservedCapacityPurchases", 
         "Effect": "Deny", 
         "Action": "dynamodb:PurchaseReservedCapacityOfferings", 
         "Resource": "arn:aws:dynamodb:us-west-2:155556789012:*" 
      } 
   ] 
}

Concessão de privilégios: usando o console da GUI

Você também pode usar o console da GUI para criar políticas IAM. Para começar, escolhaTablesno painel de navegação. Na lista de tabelas, escolha a tabela de destino e siga estas etapas.

Step 1 - Selecione o Access control aba.

Step 2- Selecione o provedor de identidade, ações e atributos de política. SelecioneCreate policy depois de inserir todas as configurações.

Step 3 - Escolha Attach policy instructionse conclua cada etapa necessária para associar a política à função IAM apropriada.

A API do DynamoDB oferece um grande conjunto de ações, que requerem permissões. Ao definir permissões, você deve estabelecer as ações permitidas, os recursos permitidos e as condições de cada um.

Você pode especificar ações no campo Ação da política. Especifique o valor do recurso no campo Recurso da política. Mas certifique-se de usar a sintaxe correta contendo o prefixo Dynamodb: com a operação da API.

Por exemplo - dynamodb:CreateTable

Você também pode empregar chaves de condição para filtrar permissões.

Permissões e ações de API

Dê uma boa olhada nas ações da API e nas permissões associadas fornecidas na tabela a seguir -

Operação API Permissão Necessária
BatchGetItem dynamodb: BatchGetItem
BatchWriteItem dynamodb: BatchWriteItem
Criar a tabela dynamodb: CreateTable
Apagar item dynamodb: DeleteItem
DeleteTable dynamodb: DeleteTable
DescribeLimits dynamodb: DescribeLimits
DescribeReservedCapacity dynamodb: DescribeReservedCapacity
DescribeReservedCapacityOfferings dynamodb: DescribeReservedCapacityOfferings
DescribeStream dynamodb: DescribeStream
DescribeTable dynamodb: DescribeTable
GetItem dynamodb: GetItem
GetRecords dynamodb: GetRecords
GetShardIterator dynamodb: GetShardIterator
ListStreams dynamodb: ListStreams
ListTables dynamodb: ListTables
PurchaseReservedCapacityOfferings dynamodb: PurchaseReservedCapacityOfferings
PutItem dynamodb: PutItem
Inquerir dynamodb: Query
Varredura dynamodb: Scan
UpdateItem dynamodb: UpdateItem
UpdateTable dynamodb: UpdateTable

Recursos

Na tabela a seguir, você pode revisar os recursos associados a cada ação permitida da API -

Operação API Recurso
BatchGetItem arn: aws: dynamodb: region: account-id: table / table-name
BatchWriteItem arn: aws: dynamodb: region: account-id: table / table-name
Criar a tabela arn: aws: dynamodb: region: account-id: table / table-name
Apagar item arn: aws: dynamodb: region: account-id: table / table-name
DeleteTable arn: aws: dynamodb: region: account-id: table / table-name
DescribeLimits arn: aws: dynamodb: region: account-id: *
DescribeReservedCapacity arn: aws: dynamodb: region: account-id: *
DescribeReservedCapacityOfferings arn: aws: dynamodb: region: account-id: *
DescribeStream arn: aws: dynamodb: region: account-id: table / table-name / stream / stream-label
DescribeTable arn: aws: dynamodb: region: account-id: table / table-name
GetItem arn: aws: dynamodb: region: account-id: table / table-name
GetRecords arn: aws: dynamodb: region: account-id: table / table-name / stream / stream-label
GetShardIterator arn: aws: dynamodb: region: account-id: table / table-name / stream / stream-label
ListStreams arn: aws: dynamodb: region: account-id: table / table-name / stream / *
ListTables *
PurchaseReservedCapacityOfferings arn: aws: dynamodb: region: account-id: *
PutItem arn: aws: dynamodb: region: account-id: table / table-name
Inquerir

arn: aws: dynamodb: region: account-id: table / table-name

ou

arn: aws: dynamodb: region: account-id: table / table-name / index / index-name

Varredura

arn: aws: dynamodb: region: account-id: table / table-name

ou

arn: aws: dynamodb: region: account-id: table / table-name / index / index-name

UpdateItem arn: aws: dynamodb: region: account-id: table / table-name
UpdateTable arn: aws: dynamodb: region: account-id: table / table-name

Ao conceder permissões, o DynamoDB permite especificar condições para elas por meio de uma política IAM detalhada com chaves de condição. Isso oferece suporte a configurações como acesso a itens e atributos específicos.

Note - O DynamoDB não oferece suporte a nenhuma tag.

Controle Detalhado

Várias condições permitem a especificidade de itens e atributos, como a concessão de acesso somente leitura a itens específicos com base na conta do usuário. Implemente esse nível de controle com políticas IAM condicionadas, que gerenciam as credenciais de segurança. Em seguida, basta aplicar a política aos usuários, grupos e funções desejados. A Federação de identidade da Web, um tópico discutido posteriormente, também fornece uma maneira de controlar o acesso do usuário por meio de logins da Amazon, Facebook e Google.

O elemento de condição da política do IAM implementa o controle de acesso. Você simplesmente o adiciona a uma política. Um exemplo de seu uso consiste em negar ou permitir o acesso aos itens e atributos da tabela. O elemento de condição também pode empregar chaves de condição para limitar as permissões.

Você pode revisar os dois exemplos a seguir das chaves de condição -

  • dynamodb:LeadingKeys - Impede o acesso ao item por usuários sem um ID correspondente ao valor da chave de partição.

  • dynamodb:Attributes - Impede que os usuários acessem ou operem em atributos fora dos listados.

Na avaliação, as políticas do IAM resultam em um valor verdadeiro ou falso. Se alguma parte for avaliada como falsa, toda a política será avaliada como falsa, o que resulta na negação de acesso. Certifique-se de especificar todas as informações necessárias nas chaves de condição para garantir que os usuários tenham acesso apropriado.

Chaves de condição predefinidas

A AWS oferece uma coleção de chaves de condição predefinidas, que se aplicam a todos os serviços. Eles suportam uma ampla gama de usos e detalhes finos no exame de usuários e acesso.

Note - Há distinção entre maiúsculas e minúsculas nas chaves de condição.

Você pode revisar uma seleção das seguintes chaves específicas do serviço -

  • dynamodb:LeadingKey- Representa o primeiro atributo chave de uma tabela; a chave de partição. Use o modificador ForAllValues ​​nas condições.

  • dynamodb:Select- Representa um parâmetro de seleção de solicitação de consulta / verificação. Deve ter o valor ALL_ATTRIBUTES, ALL_PROJECTED_ATTRIBUTES, SPECIFIC_ATTRIBUTES ou COUNT.

  • dynamodb:Attributes- Representa uma lista de nomes de atributos em uma solicitação ou atributos retornados de uma solicitação. Seus valores e suas funções se assemelham aos parâmetros de ação da API, por exemplo, BatchGetItem usa AttributesToGet.

  • dynamodb:ReturnValues - Representa o parâmetro ReturnValues ​​de uma solicitação e pode usar estes valores: ALL_OLD, UPDATED_OLD, ALL_NEW, UPDATED_NEW e NONE.

  • dynamodb:ReturnConsumedCapacity - Representa o parâmetro ReturnConsumedCapacity de uma solicitação e pode usar estes valores: TOTAL e NONE.

A Federação de identidade da Web permite simplificar a autenticação e autorização para grandes grupos de usuários. Você pode ignorar a criação de contas individuais e exigir que os usuários façam login em um provedor de identidade para obter credenciais ou tokens temporários. Ele usa o AWS Security Token Service (STS) para gerenciar credenciais. Os aplicativos usam esses tokens para interagir com os serviços.

O Web Identity Federation também oferece suporte a outros provedores de identidade, como Amazon, Google e Facebook.

Function- Em uso, o Web Identity Federation primeiro chama um provedor de identidade para autenticação de usuário e aplicativo, e o provedor retorna um token. Isso resulta na chamada do aplicativo AWS STS e na passagem do token para entrada. O STS autoriza o aplicativo e concede a ele credenciais de acesso temporário, o que permite que o aplicativo use uma função IAM e acesse recursos com base na política.

Implementando Federação de Identidade da Web

Você deve executar as três etapas a seguir antes de usar -

  • Use um provedor de identidade de terceiros com suporte para se registrar como desenvolvedor.

  • Registre seu aplicativo com o provedor para obter um ID de aplicativo.

  • Crie uma ou várias funções de IAM, incluindo o anexo de política. Você deve usar uma função por provedor por aplicativo.

Assuma uma de suas funções de IAM para usar o Web Identity Federation. Seu aplicativo deve então executar um processo de três etapas -

  • Authentication
  • Aquisição de credencial
  • Acesso a recursos

Na primeira etapa, seu aplicativo usa sua própria interface para chamar o provedor e, em seguida, gerencia o processo de token.

Em seguida, a etapa dois gerencia tokens e exige que seu aplicativo envie um AssumeRoleWithWebIdentitysolicitação para AWS STS. A solicitação contém o primeiro token, o ID do aplicativo do provedor e o ARN da função IAM. O STS fornece credenciais definidas para expirar após um determinado período.

Na etapa final, seu aplicativo recebe uma resposta do STS contendo informações de acesso para recursos do DynamoDB. Consiste em credenciais de acesso, tempo de expiração, função e ID da função.

O Data Pipeline permite exportar e importar dados de / para uma tabela, arquivo ou bucket do S3. É claro que isso é útil em backups, testes e para necessidades ou cenários semelhantes.

Em uma exportação, você usa o console do Data Pipeline, que cria um novo pipeline e inicia um cluster Amazon EMR (Elastic MapReduce) para realizar a exportação. Um EMR lê dados do DynamoDB e grava no destino. Discutimos o EMR em detalhes posteriormente neste tutorial.

Em uma operação de importação, você usa o console do Data Pipeline, que cria um pipeline e inicia o EMR para realizar a importação. Ele lê dados da origem e grava no destino.

Note - As operações de exportação / importação têm um custo face aos serviços utilizados, nomeadamente, EMR e S3.

Usando pipeline de dados

Você deve especificar permissões de ação e recurso ao usar o Data Pipeline. Você pode utilizar uma função ou política do IAM para defini-los. Os usuários que estão realizando importações / exportações devem observar que precisam de um ID de chave de acesso ativo e uma chave secreta.

Funções de IAM para pipeline de dados

Você precisa de duas funções IAM para usar o Data Pipeline -

  • DataPipelineDefaultRole - Contém todas as ações que você permite que o pipeline execute para você.

  • DataPipelineDefaultResourceRole - Isso tem recursos que você permite que o pipeline forneça para você.

Se você é novo no Data Pipeline, deve gerar cada função. Todos os usuários anteriores possuem essas funções devido às funções existentes.

Use o console IAM para criar funções IAM para Data Pipeline e execute as quatro etapas a seguir -

Step 1 - Faça login no console IAM localizado em https://console.aws.amazon.com/iam/

Step 2 - Selecione Roles do painel.

Step 3 - Selecione Create New Role. Em seguida, insira DataPipelineDefaultRole noRole Name campo e selecione Next Step. NoAWS Service Roles lista no Role Type painel, navegue para Data Pipelinee escolha Select. SelecioneCreate Role no Review painel.

Step 4 - Selecione Create New Role.

Utilize a funcionalidade de importação / exportação do Data Pipeline para realizar backups. A maneira como você executa um backup depende se você usa o console da GUI ou usa o Data Pipeline diretamente (API). Crie pipelines separados para cada tabela ao usar o console ou importe / exporte várias tabelas em um único pipeline, se estiver usando uma opção direta.

Exportando e importando dados

Você deve criar um bucket do Amazon S3 antes de realizar uma exportação. Você pode exportar de uma ou mais tabelas.

Execute o seguinte processo de quatro etapas para executar uma exportação -

Step 1 - Faça login no AWS Management Console e abra o console do Data Pipeline localizado em https://console.aws.amazon.com/datapipeline/

Step 2 - Se você não tiver pipelines na região AWS usada, selecione Get started now. Se você tiver um ou mais, selecioneCreate new pipeline.

Step 3- Na página de criação, insira um nome para seu pipeline. EscolherBuild using a templatepara o parâmetro Source. SelecioneExport DynamoDB table to S3da lista. Insira a tabela de origem noSource DynamoDB table name campo.

Insira o balde S3 de destino no Output S3 Foldercaixa de texto usando o seguinte formato: s3: // nameOfBucket / region / nameOfFolder. Insira um destino S3 para o arquivo de log emS3 location for logs caixa de texto.

Step 4 - Selecione Activate depois de inserir todas as configurações.

O pipeline pode levar vários minutos para concluir seu processo de criação. Use o console para monitorar seu status. Confirme o processamento bem-sucedido com o console S3 visualizando o arquivo exportado.

Importando Dados

Importações bem-sucedidas só podem acontecer se as seguintes condições forem verdadeiras: você criou uma tabela de destino, o destino e a origem usam nomes idênticos e o destino e a origem usam esquema de chave idêntico.

Você pode usar uma tabela de destino preenchida, no entanto, as importações substituem os itens de dados que compartilham uma chave com os itens de origem e também adicionam itens em excesso à tabela. O destino também pode usar uma região diferente.

Embora você possa exportar várias fontes, você só pode importar uma por operação. Você pode realizar uma importação seguindo as seguintes etapas -

Step 1 - Faça login no AWS Management Console e, em seguida, abra o console do Data Pipeline.

Step 2 - Se você pretende executar uma importação entre regiões, deve selecionar a região de destino.

Step 3 - Selecione Create new pipeline.

Step 4 - Insira o nome do pipeline no Namecampo. EscolherBuild using a template para o parâmetro Fonte e na lista de modelos, selecione Import DynamoDB backup data from S3.

Insira a localização do arquivo de origem no Input S3 Foldercaixa de texto. Insira o nome da tabela de destino noTarget DynamoDB table namecampo. Em seguida, insira a localização do arquivo de log noS3 location for logs caixa de texto.

Step 5 - Selecione Activate depois de inserir todas as configurações.

A importação começa imediatamente após a criação do pipeline. O pipeline pode levar vários minutos para concluir o processo de criação.

Erros

Quando ocorrem erros, o console do Data Pipeline exibe ERROR como o status do pipeline. Clicar no pipeline com um erro leva você à página de detalhes, que revela todas as etapas do processo e o ponto em que a falha ocorreu. Os arquivos de log também fornecem algumas dicas.

Você pode revisar as causas comuns dos erros da seguinte maneira -

  • A tabela de destino para uma importação não existe ou não usa esquema de chave idêntico ao da origem.

  • O bucket S3 não existe ou você não tem permissões de leitura / gravação para ele.

  • O pipeline atingiu o tempo limite.

  • Você não tem as permissões de exportação / importação necessárias.

  • Sua conta AWS atingiu o limite de recursos.

A Amazon oferece CloudWatch para agregar e analisar desempenho por meio do console CloudWatch, linha de comando ou API CloudWatch. Você também pode usá-lo para definir alarmes e executar tarefas. Ele executa ações específicas em certos eventos.

Cloudwatch Console

Utilize o CloudWatch acessando o console de gerenciamento e, em seguida, abrindo o console do CloudWatch em https://console.aws.amazon.com/cloudwatch/.

Você pode então realizar as seguintes etapas -

  • Selecione Metrics no painel de navegação.

  • Sob as métricas do DynamoDB dentro do CloudWatch Metrics by Category painel, escolha Table Metrics.

  • Use o painel superior para rolar abaixo e examinar toda a lista de métricas da tabela. oViewing lista fornece opções de métricas.

Na interface de resultados, você pode selecionar / desmarcar cada métrica marcando a caixa de seleção ao lado do nome do recurso e da métrica. Então você poderá ver os gráficos de cada item.

Integração API

Você pode acessar o CloudWatch com consultas. Use valores métricos para executar ações do CloudWatch. Observação O DynamoDB não envia métricas com valor zero. Ele simplesmente ignora as métricas por períodos de tempo em que essas métricas permanecem nesse valor.

A seguir estão algumas das métricas mais comumente usadas -

  • ConditionalCheckFailedRequests- Ele rastreia a quantidade de tentativas malsucedidas de gravações condicionais, como gravações PutItem condicionais. As gravações com falha incrementam essa métrica em um na avaliação para falsa. Ele também gera um erro HTTP 400.

  • ConsumedReadCapacityUnits- Quantifica as unidades de capacidade utilizadas durante um determinado período de tempo. Você pode usar isso para examinar o consumo individual de tabelas e índices.

  • ConsumedWriteCapacityUnits- Quantifica as unidades de capacidade utilizadas durante um determinado período de tempo. Você pode usar isso para examinar o consumo individual de tabelas e índices.

  • ReadThrottleEvents- Quantifica as solicitações que excedem as unidades de capacidade provisionadas em leituras de tabela / índice. Ele aumenta em cada aceleração, incluindo operações em lote com várias acelerações.

  • ReturnedBytes - Quantifica os bytes retornados em operações de recuperação dentro de um determinado período de tempo.

  • ReturnedItemCount- Quantifica os itens retornados nas operações de Consulta e Varredura em um determinado período de tempo. Ele aborda apenas os itens devolvidos, não os avaliados, que normalmente são valores totalmente diferentes.

Note - Existem muito mais métricas, e a maioria delas permite calcular médias, somas, máximo, mínimo e contagem.

O DynamoDB inclui integração com CloudTrail. Ele captura solicitações de API de baixo nível de ou para o DynamoDB em uma conta e envia arquivos de log para um bucket S3 especificado. Ele direciona chamadas do console ou API. Você pode usar esses dados para determinar as solicitações feitas e sua origem, usuário, carimbo de data / hora e muito mais.

Quando habilitado, ele rastreia ações em arquivos de log, que incluem outros registros de serviço. Suporta oito ações e dois fluxos -

As oito ações são as seguintes -

  • CreateTable
  • DeleteTable
  • DescribeTable
  • ListTables
  • UpdateTable
  • DescribeReservedCapacity
  • DescribeReservedCapacityOfferings
  • PurchaseReservedCapacityOfferings

Enquanto, os dois fluxos são -

  • DescribeStream
  • ListStreams

Todos os logs contêm informações sobre contas que fazem solicitações. Você pode determinar informações detalhadas, como se os usuários root ou IAM fizeram a solicitação ou se com credenciais temporárias ou federadas.

Os arquivos de log permanecem armazenados pelo tempo que você especificar, com configurações para arquivamento e exclusão. O padrão cria logs criptografados. Você pode definir alertas para novos logs. Você também pode organizar vários registros, entre regiões e contas, em um único intervalo.

Interpretando arquivos de log

Cada arquivo contém uma ou várias entradas. Cada entrada consiste em vários eventos de formato JSON. Uma entrada representa uma solicitação e inclui informações associadas; sem garantia de ordem.

Você pode revisar o seguinte arquivo de log de amostra -

{"Records": [ 
   { 
      "eventVersion": "5.05",  
      "userIdentity": {
         "type": "AssumedRole", 
         "principalId": "AKTTIOSZODNN8SAMPLE:jane", 
         "arn": "arn:aws:sts::155522255533:assumed-role/users/jane", 
         "accountId": "155522255533", 
         "accessKeyId": "AKTTIOSZODNN8SAMPLE", 
         
         "sessionContext": { 
            "attributes": { 
               "mfaAuthenticated": "false", 
               "creationDate": "2016-05-11T19:01:01Z" 
            },
            
            "sessionIssuer": { 
               "type": "Role", 
               "principalId": "AKTTI44ZZ6DHBSAMPLE", 
               "arn": "arn:aws:iam::499955777666:role/admin-role", 
               "accountId": "499955777666", 
               "userName": "jill" 
            } 
         } 
      },
      
      "eventTime": "2016-05-11T14:33:20Z", 
      "eventSource": "dynamodb.amazonaws.com", 
      "eventName": "DeleteTable", 
      "awsRegion": "us-west-2", 
      "sourceIPAddress": "192.0.2.0", 
      "userAgent": "console.aws.amazon.com", 
      "requestParameters": {"tableName": "Tools"}, 
      
      "responseElements": {"tableDescription": { 
         "tableName": "Tools", 
         "itemCount": 0, 
         
         "provisionedThroughput": { 
            "writeCapacityUnits": 25, 
            "numberOfDecreasesToday": 0, 
            "readCapacityUnits": 25 
         },
         "tableStatus": "DELETING", 
         "tableSizeBytes": 0
      }},
      "requestID": "4D89G7D98GF7G8A7DF78FG89AS7GFSO5AEMVJF66Q9ASUAAJG", 
      "eventID": "a954451c-c2fc-4561-8aea-7a30ba1fdf52", 
      "eventType": "AwsApiCall", 
      "apiVersion": "2013-04-22", 
      "recipientAccountId": "155522255533" 
   } 
]}

O Elastic MapReduce (EMR) da Amazon permite que você processe big data de maneira rápida e eficiente. O EMR executa o Apache Hadoop em instâncias EC2, mas simplifica o processo. Você utiliza o Apache Hive para consultar o mapa e reduzir os fluxos de trabalho por meio do HiveQL , uma linguagem de consulta semelhante ao SQL. O Apache Hive serve como uma forma de otimizar as consultas e seus aplicativos.

Você pode usar a guia EMR do console de gerenciamento, o EMR CLI, uma API ou um SDK para iniciar um fluxo de trabalho. Você também tem a opção de executar o Hive interativamente ou utilizar um script.

As operações de leitura / gravação EMR afetam o consumo de taxa de transferência, no entanto, em grandes solicitações, ele executa novas tentativas com a proteção de um algoritmo de backoff. Além disso, executar o EMR simultaneamente com outras operações e tarefas pode resultar em limitação.

A integração DynamoDB / EMR não oferece suporte a atributos de conjuntos binários e binários.

Pré-requisitos de integração DynamoDB / EMR

Revise esta lista de verificação de itens necessários antes de usar EMR -

  • Uma conta AWS
  • Uma tabela preenchida sob a mesma conta empregada em operações EMR
  • Uma versão Hive personalizada com conectividade DynamoDB
  • Suporte de conectividade DynamoDB
  • Um balde S3 (opcional)
  • Um cliente SSH (opcional)
  • Um par de chaves EC2 (opcional)

Configuração de colmeia

Antes de usar o EMR, crie um par de chaves para executar o Hive no modo interativo. O par de chaves permite a conexão com instâncias EC2 e nós mestres de fluxos de trabalho.

Você pode fazer isso seguindo as etapas subsequentes -

  • Faça login no console de gerenciamento e abra o console EC2 localizado em https://console.aws.amazon.com/ec2/

  • Selecione uma região na parte superior direita do console. Certifique-se de que a região corresponda à região do DynamoDB.

  • No painel de navegação, selecione Key Pairs.

  • Selecione Create Key Pair.

  • No Key Pair Name campo, digite um nome e selecione Create.

  • Faça download do arquivo de chave privada resultante que usa o seguinte formato: filename.pem.

Note - Você não pode se conectar a instâncias EC2 sem o par de chaves.

Hive Cluster

Crie um cluster habilitado para hive para executar o Hive. Ele constrói o ambiente necessário de aplicativos e infraestrutura para uma conexão Hive-para-DynamoDB.

Você pode executar esta tarefa usando as seguintes etapas -

  • Acesse o console EMR.

  • Selecione Create Cluster.

  • Na tela de criação, defina a configuração do cluster com um nome descritivo para o cluster, selecione Yes para proteção de terminação e verifique Enabled para registro, um destino S3 para log folder S3 location, e Enabled para depuração.

  • Na tela de configuração de software, certifique-se de que os campos sejam mantidos Amazon para distribuição do Hadoop, a versão mais recente para a versão AMI, uma versão padrão do Hive para aplicativos a serem instalados-Hive e uma versão padrão do Pig para aplicativos a serem instalados-Pig.

  • Na tela de configuração de hardware, certifique-se de que os campos sejam mantidos Launch into EC2-Classic para rede, No Preference para EC2 Availability Zone, o padrão para Master-Amazon EC2 Instance Type, nenhuma verificação para Request Spot Instances, o padrão para Core-Amazon EC2 Instance Type, 2 para Contagem, sem verificação para Solicitar Instâncias Spot, o padrão para Task-Amazon EC2 Instance Type, 0 para Contagem e sem verificação para Instâncias Spot de Solicitação.

Certifique-se de definir um limite com capacidade suficiente para evitar a falha do cluster.

  • Na tela Segurança e acesso, certifique-se de que os campos contenham seu par de chaves no par de chaves EC2, No other IAM users no acesso do usuário IAM, e Proceed without roles na função IAM.

  • Revise a tela Bootstrap Actions, mas não a modifique.

  • Revise as configurações e selecione Create Cluster quando terminado.

UMA Summary painel aparece no início do cluster.

Ativar Sessão SSH

Você precisa de uma sessão SSH ativa para se conectar ao nó mestre e executar as operações CLI. Localize o nó mestre selecionando o cluster no console EMR. Ele lista o nó mestre comoMaster Public DNS Name.

Instale o PuTTY se não o tiver. Em seguida, inicie o PuTTYgen e selecioneLoad. Escolha seu arquivo PEM e abra-o. PuTTYgen irá informá-lo sobre a importação bem-sucedida. SelecioneSave private key para salvar no formato de chave privada PuTTY (PPK) e escolha Yespara salvar sem uma frase secreta. Em seguida, digite um nome para a chave PuTTY, pressioneSavee feche o PuTTYgen.

Use PuTTY para fazer uma conexão com o nó mestre, iniciando primeiro o PuTTY. EscolherSessionna lista de categorias. Digite hadoop @ DNS no campo Host Name. ExpandirConnection > SSH na lista de categorias e escolha Auth. Na tela de opções de controle, selecioneBrowsepara arquivo de chave privada para autenticação. Em seguida, selecione seu arquivo de chave privada e abra-o. SelecioneYes para o pop-up de alerta de segurança.

Quando conectado ao nó mestre, um prompt de comando do Hadoop aparece, o que significa que você pode iniciar uma sessão interativa do Hive.

Mesa Colmeia

O Hive serve como uma ferramenta de armazenamento de dados, permitindo consultas em clusters EMR usando HiveQL . As configurações anteriores fornecem um prompt de trabalho. Execute os comandos do Hive interativamente, simplesmente inserindo “hive” e, a seguir, quaisquer comandos que desejar. Consulte nosso tutorial do Hive para obter mais informações sobre o Hive .

Os fluxos do DynamoDB permitem que você rastreie e responda às alterações dos itens da tabela. Empregue esta funcionalidade para criar um aplicativo que responde às mudanças atualizando as informações entre as fontes. Sincronize dados para milhares de usuários de um grande sistema multiusuário. Use-o para enviar notificações aos usuários sobre atualizações. Suas aplicações são diversas e substanciais. Os streams do DynamoDB servem como a principal ferramenta usada para atingir essa funcionalidade.

Os streams capturam sequências ordenadas por tempo contendo modificações de itens em uma tabela. Eles mantêm esses dados por no máximo 24 horas. Os aplicativos os usam para visualizar os itens originais e modificados, quase em tempo real.

Os fluxos ativados em uma tabela capturam todas as modificações. Em qualquer operação CRUD, o DynamoDB cria um registro de fluxo com os atributos-chave primários dos itens modificados. Você pode configurar streams para obter informações adicionais, como imagens anteriores e posteriores.

Os Streams trazem duas garantias -

  • Cada registro aparece uma vez no stream e

  • Cada modificação de item resulta nos registros de fluxo da mesma ordem das modificações.

Todos os fluxos são processados ​​em tempo real para permitir que você os utilize para funcionalidades relacionadas em aplicativos.

Gerenciando Streams

Na criação da mesa, você pode habilitar um fluxo. As tabelas existentes permitem a desativação do fluxo ou alterações nas configurações. Streams oferecem o recurso de operação assíncrona, o que significa nenhum impacto no desempenho da tabela.

Utilize o console de gerenciamento da AWS para gerenciamento de fluxo simples. Primeiro, navegue até o console e escolhaTables. Na guia Visão geral, escolhaManage Stream. Dentro da janela, selecione as informações adicionadas a um fluxo nas modificações de dados da tabela. Depois de inserir todas as configurações, selecioneEnable.

Se você deseja desativar qualquer fluxo existente, selecione Manage Stream, e depois Disable.

Você também pode utilizar as APIs CreateTable e UpdateTable para habilitar ou alterar um fluxo. Use o parâmetro StreamSpecification para configurar o fluxo. StreamEnabled especifica o status, significando verdadeiro para habilitado e falso para desabilitado.

StreamViewType especifica as informações adicionadas ao fluxo: KEYS_ONLY, NEW_IMAGE, OLD_IMAGE e NEW_AND_OLD_IMAGES.

Leitura de fluxo

Leia e processe fluxos conectando-se a um terminal e fazendo solicitações de API. Cada fluxo consiste em registros de fluxo e cada registro existe como uma única modificação que possui o fluxo. Os registros de fluxo incluem um número de sequência que revela a ordem de publicação. Os registros pertencem a grupos também conhecidos como fragmentos. Os fragmentos funcionam como contêineres para vários registros e também contêm informações necessárias para acessar e percorrer os registros. Após 24 horas, os registros são excluídos automaticamente.

Esses fragmentos são gerados e excluídos conforme necessário e não duram muito. Eles também se dividem em vários novos shards automaticamente, geralmente em resposta a picos de atividade de gravação. Desativando na transmissão, feche os fragmentos abertos. O relacionamento hierárquico entre os shards significa que os aplicativos devem priorizar os shards pais para a ordem de processamento correta. Você pode usar o adaptador Kinesis para fazer isso automaticamente.

Note - As operações que resultam em nenhuma mudança não gravam registros de fluxo.

Para acessar e processar registros, é necessário realizar as seguintes tarefas -

  • Determine o ARN do fluxo de destino.
  • Determine o (s) fragmento (s) do fluxo que contém os registros de destino.
  • Acesse o (s) fragmento (s) para recuperar os registros desejados.

Note- Deve haver no máximo 2 processos lendo um fragmento de uma vez. Se exceder 2 processos, pode estrangular a fonte.

As ações da API de fluxo disponíveis incluem

  • ListStreams
  • DescribeStream
  • GetShardIterator
  • GetRecords

Você pode revisar o seguinte exemplo de leitura de fluxo -

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBStreamsClient;

import com.amazonaws.services.dynamodbv2.model.AttributeAction;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate;

import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.DescribeStreamRequest;
import com.amazonaws.services.dynamodbv2.model.DescribeStreamResult;
import com.amazonaws.services.dynamodbv2.model.DescribeTableResult;

import com.amazonaws.services.dynamodbv2.model.GetRecordsRequest;
import com.amazonaws.services.dynamodbv2.model.GetRecordsResult;
import com.amazonaws.services.dynamodbv2.model.GetShardIteratorRequest;
import com.amazonaws.services.dynamodbv2.model.GetShardIteratorResult;

import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.Record;

import com.amazonaws.services.dynamodbv2.model.Shard;
import com.amazonaws.services.dynamodbv2.model.ShardIteratorType;
import com.amazonaws.services.dynamodbv2.model.StreamSpecification;
import com.amazonaws.services.dynamodbv2.model.StreamViewType;
import com.amazonaws.services.dynamodbv2.util.Tables;

public class StreamsExample {
   private static AmazonDynamoDBClient dynamoDBClient =  
      new AmazonDynamoDBClient(new ProfileCredentialsProvider());  
   private static AmazonDynamoDBStreamsClient streamsClient =  
      new AmazonDynamoDBStreamsClient(new ProfileCredentialsProvider());  

   public static void main(String args[]) {  
      dynamoDBClient.setEndpoint("InsertDbEndpointHere");   
      streamsClient.setEndpoint("InsertStreamEndpointHere");    
      
      // table creation 
      String tableName = "MyTestingTable";  
      ArrayList<AttributeDefinition> attributeDefinitions =  
         new ArrayList<AttributeDefinition>();  
      
      attributeDefinitions.add(new AttributeDefinition()
         .withAttributeName("ID") 
         .withAttributeType("N"));
         
      ArrayList<KeySchemaElement> keySchema = new 
         ArrayList<KeySchemaElement>(); 
      
      keySchema.add(new KeySchemaElement() 
         .withAttributeName("ID") 
         .withKeyType(KeyType.HASH));                       //Partition key

      StreamSpecification streamSpecification = new StreamSpecification(); 
      streamSpecification.setStreamEnabled(true); 
      streamSpecification.setStreamViewType(StreamViewType.NEW_AND_OLD_IMAGES);  
      CreateTableRequest createTableRequest = new CreateTableRequest() 
         .withTableName(tableName) 
         .withKeySchema(keySchema) 
         .withAttributeDefinitions(attributeDefinitions) 
         .withProvisionedThroughput(new ProvisionedThroughput() 
         .withReadCapacityUnits(1L) 
         .withWriteCapacityUnits(1L))
         .withStreamSpecification(streamSpecification);  
      
      System.out.println("Executing CreateTable for " + tableName); 
      dynamoDBClient.createTable(createTableRequest);  
      System.out.println("Creating " + tableName); 
      
      try { 
         Tables.awaitTableToBecomeActive(dynamoDBClient, tableName); 
      } catch (InterruptedException e) { 
         e.printStackTrace(); 
      } 
         
      // Get the table's stream settings 
      DescribeTableResult describeTableResult =
         dynamoDBClient.describeTable(tableName);  
      
      String myStreamArn = describeTableResult.getTable().getLatestStreamArn(); 
      StreamSpecification myStreamSpec =  
         describeTableResult.getTable().getStreamSpecification();  
      
      System.out.println("Current stream ARN for " + tableName + ": "+ myStreamArn);
      System.out.println("Stream enabled: "+ myStreamSpec.getStreamEnabled()); 
      System.out.println("Update view type: "+ myStreamSpec.getStreamViewType());  
      
      // Add an item 
      int numChanges = 0; 
      System.out.println("Making some changes to table data"); 
      Map<String, AttributeValue> item = new HashMap<String, AttributeValue>(); 
      item.put("ID", new AttributeValue().withN("222")); 
      item.put("Alert", new AttributeValue().withS("item!")); 
      dynamoDBClient.putItem(tableName, item); 
      numChanges++;  
      
      // Update the item         
      Map<String, AttributeValue> key = new HashMap<String, AttributeValue>(); 
      key.put("ID", new AttributeValue().withN("222")); 
      Map<String, AttributeValueUpdate> attributeUpdates =  
      new HashMap<String, AttributeValueUpdate>(); 
      
      attributeUpdates.put("Alert", new AttributeValueUpdate() 
         .withAction(AttributeAction.PUT) 
         .withValue(new AttributeValue().withS("modified item"))); 
      
      dynamoDBClient.updateItem(tableName, key, attributeUpdates); 
      numChanges++;   
      
      // Delete the item         
      dynamoDBClient.deleteItem(tableName, key);  
      numChanges++;
      
      // Get stream shards         
      DescribeStreamResult describeStreamResult =  
      streamsClient.describeStream(new DescribeStreamRequest() 
         .withStreamArn(myStreamArn)); 
      String streamArn =  
         describeStreamResult.getStreamDescription().getStreamArn(); 
      List<Shard> shards =  
         describeStreamResult.getStreamDescription().getShards();  
      
      // Process shards 
      for (Shard shard : shards) { 
         String shardId = shard.getShardId(); 
         System.out.println("Processing " + shardId + " in "+ streamArn);  
         
         // Get shard iterator 
         GetShardIteratorRequest getShardIteratorRequest = new 
            GetShardIteratorRequest() 
            .withStreamArn(myStreamArn) 
            .withShardId(shardId) 
            .withShardIteratorType(ShardIteratorType.TRIM_HORIZON); 
         
         GetShardIteratorResult getShardIteratorResult =  
            streamsClient.getShardIterator(getShardIteratorRequest); 
         String nextItr = getShardIteratorResult.getShardIterator();  
         
         while (nextItr != null && numChanges > 0) { 
            // Read data records with iterator                 
            GetRecordsResult getRecordsResult =  
               streamsClient.getRecords(new GetRecordsRequest(). 
               withShardIterator(nextItr));
               
            List<Record> records = getRecordsResult.getRecords(); 
            System.out.println("Pulling records...");  
               
            for (Record record : records) { 
               System.out.println(record); 
               numChanges--;
            } 
            nextItr = getRecordsResult.getNextShardIterator(); 
         } 
      } 
   } 
}

No processamento malsucedido de uma solicitação, o DynamoDB gera um erro. Cada erro consiste nos seguintes componentes: código de status HTTP, nome da exceção e mensagem. O gerenciamento de erros depende de seu SDK, que propaga erros, ou de seu próprio código.

Códigos e Mensagens

As exceções se enquadram em diferentes códigos de status de cabeçalho HTTP. O 4xx e o 5xx contêm erros relacionados a problemas de solicitação e AWS.

Uma seleção de exceções na categoria HTTP 4xx são as seguintes -

  • AccessDeniedException - O cliente não conseguiu assinar o pedido corretamente.

  • ConditionalCheckFailedException - Uma condição avaliada como falsa.

  • IncompleteSignatureException - O pedido incluía uma assinatura incompleta.

As exceções na categoria HTTP 5xx são as seguintes -

  • Erro do Servidor Interno
  • Serviço indisponível

Algoritmos de tentativas e backoff

Os erros vêm de uma variedade de fontes, como servidores, switches, balanceadores de carga e outras peças de estruturas e sistemas. As soluções comuns consistem em novas tentativas simples, que oferecem suporte à confiabilidade. Todos os SDKs incluem essa lógica automaticamente e você pode definir parâmetros de repetição para atender às necessidades de seu aplicativo.

For example - Java oferece um valor maxErrorRetry para interromper as novas tentativas.

A Amazon recomenda o uso de uma solução de backoff, além de novas tentativas, para controlar o fluxo. Isso consiste em aumentar progressivamente os períodos de espera entre as novas tentativas e, eventualmente, parar após um período bastante curto. Observação SDKs realizam novas tentativas automáticas, mas não backoff exponencial.

O programa a seguir é um exemplo de recuo de nova tentativa -

public enum Results { 
   SUCCESS,  
   NOT_READY,  
   THROTTLED,  
   SERVER_ERROR 
}
public static void DoAndWaitExample() {  
   try {
      // asynchronous operation. 
      long token = asyncOperation();  
      int retries = 0; 
      boolean retry = false;  
      
      do { 
         long waitTime = Math.min(getWaitTime(retries), MAX_WAIT_INTERVAL);  
         System.out.print(waitTime + "\n");  
         
         // Pause for result 
         Thread.sleep(waitTime);  
         
         // Get result 
         Results result = getAsyncOperationResult(token);  
         
         if (Results.SUCCESS == result) { 
            retry = false; 
         } else if (Results.NOT_READY == result) { 
            retry = true; 
         } else if (Results.THROTTLED == result) { 
            retry = true; 
         } else if (Results.SERVER_ERROR == result) { 
            retry = true; 
         } else { 
            
            // stop on other error 
            retry = false; 
         }  
      } while (retry && (retries++ < MAX_RETRIES)); 
   }
   catch (Exception ex) { 
   } 
}
public static long getWaitTime(int retryCount) {  
   long waitTime = ((long) Math.pow(3, retryCount) * 100L);  
   return waitTime; 
}

Certas práticas otimizam o código, evitam erros e minimizam o custo de transferência ao trabalhar com várias fontes e elementos.

A seguir estão algumas das melhores práticas mais importantes e comumente usadas no DynamoDB.

Mesas

A distribuição de tabelas significa que as melhores abordagens distribuem a atividade de leitura / gravação de maneira uniforme em todos os itens da tabela.

Tenha como objetivo o acesso uniforme aos dados dos itens da tabela. O uso ideal da taxa de transferência depende da seleção da chave primária e dos padrões de carga de trabalho do item. Distribua a carga de trabalho uniformemente pelos valores de chave de partição. Evite coisas como uma pequena quantidade de valores de chave de partição muito usados. Opte por opções melhores, como grandes quantidades de valores de chave de partição distintos.

Compreenda o comportamento da partição. Estimar partições alocadas automaticamente pelo DynamoDB.

O DynamoDB oferece uso de taxa de transferência de pico, que reserva taxa de transferência não utilizada para “explosões” de energia. Evite o uso pesado dessa opção porque os bursts consomem grandes quantidades de throughput rapidamente; além disso, não se mostra um recurso confiável.

Em uploads, distribua os dados para obter um melhor desempenho. Implemente isso enviando para todos os servidores alocados simultaneamente.

Armazene itens usados ​​com frequência para descarregar a atividade de leitura no cache, em vez de no banco de dados.

Itens

Custos de limitação, desempenho, tamanho e acesso continuam sendo as maiores preocupações com os itens. Opte por tabelas um-para-muitos. Remova os atributos e divida as tabelas para corresponder aos padrões de acesso. Você pode melhorar drasticamente a eficiência por meio dessa abordagem simples.

Comprima grandes valores antes de armazená-los. Utilize ferramentas de compressão padrão. Use armazenamento alternativo para grandes valores de atributos, como S3. Você pode armazenar o objeto no S3 e um identificador no item.

Distribua grandes atributos em vários itens por meio de peças de itens virtuais. Isso fornece uma solução alternativa para as limitações de tamanho do item.

Consultas e varreduras

Consultas e varreduras sofrem principalmente de desafios de consumo de taxa de transferência. Evite rajadas, que normalmente resultam de coisas como mudar para uma leitura fortemente consistente. Use varreduras paralelas de uma forma com poucos recursos (ou seja, função de segundo plano sem limitação). Além disso, use-os apenas com tabelas grandes e as situações em que você não utiliza totalmente o rendimento ou as operações de varredura oferecem baixo desempenho.

Índices Secundários Locais

Os índices apresentam problemas nas áreas de custos de transferência e armazenamento e na eficiência das consultas. Evite indexar, a menos que você consulte os atributos com frequência. Nas projeções, escolha com sabedoria porque incham os índices. Selecione apenas aqueles muito usados.

Utilize índices esparsos, ou seja, índices nos quais as chaves de classificação não aparecem em todos os itens da tabela. Eles beneficiam as consultas sobre atributos não presentes na maioria dos itens da tabela.

Preste atenção na expansão da coleção de itens (todos os itens da tabela e seus índices). As operações de adicionar / atualizar fazem com que as tabelas e os índices aumentem e 10 GB permanece o limite para coleções.

Índices Secundários Globais

Os índices apresentam problemas nas áreas de custos de transferência e armazenamento e na eficiência das consultas. Opte pela difusão de atributos-chave, que, como a difusão de leitura / gravação em tabelas, fornece uniformidade de carga de trabalho. Escolha atributos que distribuem dados uniformemente. Além disso, utilize índices esparsos.

Explore índices secundários globais para pesquisas rápidas em consultas que solicitam uma quantidade modesta de dados.