Query DynamoDB su un GSI in Node.js (AWS SDK v3)

Una query su un GSI è una normale Query più IndexName, e poi due cose smettono di comportarsi come in una query su tabella: il flag di coerenza a cui sei abituato diventa un errore, e il cursore di paginazione guadagna un attributo in più. Qui AlbumTitle-index recupera i brani per album, cosa che la tabella base (Artist + SongTitle) non può fare senza uno scan.

Codice

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`);

Il cursore è largo tre attributi, non due

Esegui il loop qui sopra su 300 brani di uno stesso album e ispeziona il LastEvaluatedKey che restituisce:

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

Una chiave di GSI non è univoca, quindi la sola chiave dell'indice non può riprendere una scansione. DynamoDB restituisce insieme la chiave dell'indice e la chiave della tabella base, ed entrambe devono tornare in ExclusiveStartKey intatte. Ecco perché un cursore fatto in casa che memorizza "l'ultima sort key che ho visto" funziona su una tabella e silenziosamente perde o ripete Item su un indice — ed ecco perché persistere quella chiave su un client è una cattiva idea quando la chiave della tabella è un id utente che preferiresti non far trapelare.

ConsistentRead: true è un 400, non un upgrade

L'istinto dice che una lettura fortemente coerente costa più capacità e ti dà dati più freschi. Su un GSI ti costa la richiesta:

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

La API reference è altrettanto netta: "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." Anche Scan su un GSI rifiuta lo stesso flag con lo stesso messaggio. Gli indici secondari locali invece lo accettano.

Riprodotto il 2026-07-28 su DynamoDB Local (amazon/dynamodb-local) con @aws-sdk/client-dynamodb 3.1095.0 su node v24.18.0. Il testo dell'errore e le forme delle chiavi sono l'output del motore stesso.

Spiegazione

  • IndexName non sostituisce TableName. Vanno entrambi nello stesso comando, e la KeyConditionExpression nomina poi la partition key dell'indice (AlbumTitle), non quella della tabella, con lo stesso insieme di operatori di una query su tabella.
  • Ottieni la proiezione e nient'altro. Una query su GSI restituisce ciò che l'indice proietta (ALL, KEYS_ONLY o la lista INCLUDE), e secondo la API reference "global secondary index queries cannot fetch attributes from the parent table". Un attributo mancante significa un GetItem di follow-up sulla chiave base, oppure una proiezione più ampia e un indice ricreato.
  • Gli Item privi della chiave dell'indice non compaiono mai. È il pattern dello sparse index, ed è una funzionalità: indicizza solo le righe con status = "OPEN" e il GSI resta piccolo. È anche il motivo per cui una query su GSI può restituire meno Item di quanti te ne aspetti senza sollevare alcun errore.
  • La replica è asincrona, quindi una scrittura appena arrivata sulla tabella può non essere ancora nell'indice. Mettilo in conto nei percorsi read-after-write invece di riprovare in un loop stretto.

Fallo visivamente

Aggiungere un GSI a posteriori è il modo costoso per impararlo. Il planner per la progettazione a tabella singola prende i tuoi pattern di accesso e calcola quali di essi hanno bisogno di una chiave di indice e quali la tabella base già serve.

Per sfogliare gli indici di una tabella ed eseguire query su GSI da un modulo, con una griglia paginata, scarica DynoTable.

Esempi correlati

Riferimenti

Costruisci questa richiesta visivamente

Componi questa operazione nel Generatore di query DynamoDB gratuito — condizione di chiave, filtro, indice, Limit, ordine di ordinamento e un loop di paginazione — e copiala come programma eseguibile per SDK v3, CLI o boto3.

Apri il Generatore di query DynamoDB

Lavora con DynamoDB senza la Console

Un client desktop veloce per DynamoDB che esegue il vero SQL che DynamoDB non può — JOINs, GROUP BY, aggregazioni — con modifica visuale e un agente AI sulle tue chiavi Bedrock.

Prova gratuita di 30 giorni, senza carta di credito — poi il piano Free senza limiti di tempo.