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 400La 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
IndexNamenon sostituisceTableName. Vanno entrambi nello stesso comando, e laKeyConditionExpressionnomina 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_ONLYo la listaINCLUDE), e secondo la API reference "global secondary index queries cannot fetch attributes from the parent table". Un attributo mancante significa unGetItemdi 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
- Query DynamoDB su un GSI in Python — la stessa query su indice con boto3.
- Query DynamoDB su un GSI con la AWS CLI — la stessa query su indice dalla shell.
- Query DynamoDB in Node.js — interrogare la tabella base.
- GSI vs. LSI — quale tipo di indice si adatta al pattern di accesso.
- Perché i GSI sono a coerenza eventuale — il ritardo di replica spiegato.
- "The table does not have the specified index" — il nome dell'indice non corrisponde (i nomi dei GSI distinguono maiuscole e minuscole).
- "Consistent reads are not supported on global secondary indexes" — perché il flag di lettura fortemente coerente fallisce su un GSI.