Query em um GSI do DynamoDB em Node.js (AWS SDK v3)

Uma consulta a um GSI é um Query normal mais IndexName, e então duas coisas param de se comportar como uma consulta a tabela: a flag de consistência à qual você está acostumado vira um erro, e o cursor de paginação ganha um atributo extra. Aqui o AlbumTitle-index busca músicas por álbum, algo que a tabela base (Artist + SongTitle) não consegue fazer sem um scan.

Código

import {DynamoDBClient, QueryCommand} from '@aws-sdk/client-dynamodb';

const client = new DynamoDBClient({region: 'us-east-1'});

const items = [];
let lastEvaluatedKey;

do {
  const response = await client.send(
    new QueryCommand({
      TableName: 'Music',
      IndexName: 'AlbumTitle-index',
      KeyConditionExpression: '#hashKey = :hashKeyValue',
      ExpressionAttributeNames: {
        '#hashKey': 'AlbumTitle'
      },
      ExpressionAttributeValues: {
        ':hashKeyValue': {S: 'Danzon'}
      },
      ExclusiveStartKey: lastEvaluatedKey
    })
  );

  items.push(...(response.Items ?? []));
  lastEvaluatedKey = response.LastEvaluatedKey;
} while (lastEvaluatedKey);

console.log(`Found ${items.length} songs on the album`);

O cursor tem três atributos de largura, não dois

Execute o loop acima contra 300 músicas de um mesmo álbum e inspecione o LastEvaluatedKey que ele devolve:

table query  -> ['Artist', 'SongTitle']
GSI query    -> ['AlbumTitle', 'Artist', 'SongTitle']

Uma chave de GSI não é única, então a chave do índice sozinha não consegue retomar uma varredura. O DynamoDB retorna a chave do índice e a chave da tabela base juntas, e ambas precisam voltar em ExclusiveStartKey intactas. É por isso que um cursor feito à mão que guarda "a última chave de ordenação que eu vi" funciona em uma tabela e silenciosamente perde ou repete itens em um índice — e por que persistir essa chave em um cliente é má ideia quando a chave da tabela é um id de usuário que você prefere não vazar.

ConsistentRead: true é um 400, não um upgrade

O instinto diz que uma leitura com consistência forte custa mais capacidade e te dá dados mais frescos. Em um GSI ela te custa a requisição:

ValidationException: Consistent reads are not supported on global secondary indexes
HTTP 400

A referência da API é igualmente direta: "Strongly consistent reads are not supported on global secondary indexes. If you query a global secondary index with ConsistentRead set to true, you will receive a ValidationException." O Scan em um GSI rejeita a mesma flag com a mesma mensagem. Índices secundários locais aceitam, sim.

Reproduzido em 2026-07-28 contra o DynamoDB Local (amazon/dynamodb-local) com @aws-sdk/client-dynamodb 3.1095.0 no node v24.18.0. O texto do erro e os formatos de chave são a saída literal do motor.

Explicação

  • IndexName não substitui TableName. Os dois vão no mesmo comando, e a KeyConditionExpression então nomeia a chave de partição do índice (AlbumTitle), não a da tabela, com o mesmo conjunto de operadores de uma consulta a tabela.
  • Você recebe a projeção e nada além dela. Uma consulta a GSI retorna o que o índice projeta (ALL, KEYS_ONLY ou a lista INCLUDE), e conforme a referência da API "global secondary index queries cannot fetch attributes from the parent table". Um atributo faltando significa um GetItem de acompanhamento na chave base, ou uma projeção mais ampla e um índice recriado.
  • Itens sem a chave do índice nunca aparecem. Esse é o padrão de índice esparso, e é um recurso: indexe apenas as linhas com status = "OPEN" e o GSI fica pequeno. Também é a razão pela qual uma consulta a GSI pode retornar menos itens do que você espera sem levantar nenhum erro.
  • A replicação é assíncrona, então uma escrita que acabou de cair na tabela pode ainda não estar no índice. Considere isso nos caminhos de leitura-após-escrita em vez de tentar de novo em um loop apertado.

Faça isso visualmente

Adicionar um GSI depois do fato é a forma cara de aprender isso. O planejador de single-table design recebe seus padrões de acesso e determina quais deles precisam de uma chave de índice e quais a tabela base já atende.

Para navegar pelos índices de uma tabela e executar consultas a GSI a partir de um formulário, com uma grade paginada, baixe o DynoTable.

Exemplos relacionados

Referências

Monte esta solicitação visualmente

Componha esta operação no Construtor de Consultas do DynamoDB gratuito — key condition, filtro, índice, Limit, ordem de classificação e um laço de paginação — e copie de volta como um programa executável para SDK v3, CLI ou boto3.

Abrir o Construtor de Consultas do DynamoDB

Trabalhe com o DynamoDB sem o Console

Um cliente desktop rápido para DynamoDB que roda o SQL de verdade que o DynamoDB não consegue — JOINs, GROUP BY, agregações — com edição visual e um agente de IA com suas próprias chaves do Bedrock.

Teste grátis de 30 dias, sem cartão de crédito — depois o plano Grátis sem limite de tempo.