Query a un GSI de DynamoDB en Node.js (SDK de AWS v3)
Una consulta a un GSI es un Query normal más IndexName, y entonces dos cosas dejan de comportarse como en una consulta a la tabla: el flag de consistencia al que estás acostumbrado se convierte en un error, y el cursor de paginación gana un atributo extra. Aquí AlbumTitle-index recupera canciones por álbum, algo que la tabla base (Artist + SongTitle) no puede hacer sin un 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`);El cursor tiene tres atributos de ancho, no dos
Ejecuta el bucle de arriba contra 300 canciones de un mismo álbum e inspecciona el LastEvaluatedKey que devuelve:
table query -> ['Artist', 'SongTitle']
GSI query -> ['AlbumTitle', 'Artist', 'SongTitle']Una clave de GSI no es única, así que la clave del índice por sí sola no puede reanudar un recorrido. DynamoDB devuelve la clave del índice y la clave de la tabla base juntas, y ambas tienen que volver intactas en ExclusiveStartKey. Por eso un cursor artesanal que guarda «la última clave de ordenación que vi» funciona sobre una tabla y en silencio pierde o repite Items sobre un índice — y por eso persistir esa clave en un cliente es mala idea cuando la clave de la tabla es un id de usuario que preferirías no filtrar.
ConsistentRead: true es un 400, no una mejora
El instinto dice que una lectura fuertemente consistente cuesta más capacidad y te da datos más frescos. En un GSI te cuesta la petición:
ValidationException: Consistent reads are not supported on global secondary indexes
HTTP 400La referencia de la API es igual de tajante: "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." Scan sobre un GSI rechaza el mismo flag con el mismo mensaje. Los índices secundarios locales sí lo aceptan.
Reproducido el 2026-07-28 contra DynamoDB Local (amazon/dynamodb-local) con @aws-sdk/client-dynamodb 3.1095.0 en node v24.18.0. El texto del error y las formas de las claves son la salida propia del motor.
Explicación
IndexNameno sustituye aTableName. Ambos van en el mismo comando, y laKeyConditionExpressionnombra entonces la clave de partición del índice (AlbumTitle), no la de la tabla, con el mismo juego de operadores que una consulta a la tabla.- Obtienes la proyección y nada más. Una consulta a un GSI devuelve lo que el índice proyecta (
ALL,KEYS_ONLYo la listaINCLUDE), y según la referencia de la API "global secondary index queries cannot fetch attributes from the parent table". Un atributo que falte significa unGetItemde seguimiento sobre la clave base, o una proyección más amplia y un índice recreado. - Los Items a los que les falta la clave del índice nunca aparecen. Ese es el patrón de índice disperso, y es una característica: indexa solo las filas con
status = "OPEN"y el GSI se mantiene pequeño. También es la razón por la que una consulta a un GSI puede devolver menos Items de los que esperas sin lanzar ningún error. - La replicación es asíncrona, así que una escritura que acaba de aterrizar en la tabla puede no estar todavía en el índice. Cuenta con eso en los caminos de lectura tras escritura en lugar de reintentar en un bucle cerrado.
Hazlo visualmente
Añadir un GSI a posteriori es la forma cara de aprender esto. La herramienta de diseño de tabla única toma tus patrones de acceso y determina cuáles necesitan una clave de índice y cuáles ya sirve la tabla base.
Para explorar los índices de una tabla y ejecutar consultas a un GSI desde un formulario, con una cuadrícula paginada, descarga DynoTable.
Ejemplos relacionados
- Query a un GSI de DynamoDB en Python — la misma consulta al índice con boto3.
- Query a un GSI de DynamoDB con la AWS CLI — la misma consulta al índice desde la shell.
- Query de DynamoDB en Node.js — consultar la tabla base.
- GSI vs. LSI — qué tipo de índice encaja con el patrón de acceso.
- Por qué los GSI son eventualmente consistentes — el retardo de replicación explicado.
- «The table does not have the specified index» — el nombre del índice no coincide (los nombres de GSI distinguen mayúsculas y minúsculas).
- «Consistent reads are not supported on global secondary indexes» — por qué el flag de lectura consistente falla en un GSI.