DynamoDB Scan en Node.js (AWS SDK v3)

El do/while de abajo no es código defensivo. Una página de un Scan con filtro puede volver con un array Items vacío y aun así quedar tabla por recorrer, así que parar en la primera respuesta es la forma de que un scan informe de cero coincidencias en una tabla que sí las tiene. Query vs. Scan cubre cuándo evitar la operación por completo.

Código

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

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

const items = [];
let lastEvaluatedKey;

do {
  const response = await client.send(
    new ScanCommand({
      TableName: 'Music',
      FilterExpression: '#filter0 >= :filterValue0',
      ExpressionAttributeNames: {
        '#filter0': 'Year'
      },
      ExpressionAttributeValues: {
        ':filterValue0': {N: '2010'}
      },
      ExclusiveStartKey: lastEvaluatedKey
    })
  );

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

console.log(`Matched ${items.length} items`);

Dos páginas vacías, 284,5 unidades de lectura, 8 Items

El conjunto de prueba son 600 canciones de unos 3,9 KB cada una, de las cuales exactamente 8 tienen Year >= 2010, y quedan las últimas al ordenar. Esto es lo que recibe de verdad el bucle de arriba:

Viaje de ida y vueltaItems.lengthScannedCountUnidades de lecturaLastEvaluatedKey
10271128,5presente
20271128,5presente
385827,5ausente

Dos páginas consecutivas no devuelven nada y cuestan 128,5 unidades de lectura cada una. El código que hace if (!response.Items.length) return informa de una tabla vacía. La referencia de la API enuncia la regla sin rodeos: "a scan result can result in no items meeting the criteria and the Count will result in zero", y por separado que "a FilterExpression is applied after the items have already been read; the process of filtering does not consume any additional read capacity units".

Lee esa segunda frase como la lee tu factura. El filtro es gratis, y todo lo que descartó no lo es: 284,5 unidades de lectura para entregar 8 Items, la misma factura que pagarías sin filtro alguno.

Medido el 2026-07-28 contra DynamoDB Local (amazon/dynamodb-local) con @aws-sdk/client-dynamodb 3.1095.0 sobre node v24.18.0. Los recuentos y la capacidad son los propios campos de respuesta del motor.

Explicación

  • ExclusiveStartKey: lastEvaluatedKey es undefined en la primera pasada. El serializador de v3 descarta los miembros undefined, así que un solo objeto literal sirve para la primera petición y para todas las siguientes. Pasar {} en su lugar falla con ValidationException: The provided starting key is invalid.
  • response.Items ?? [] está haciendo trabajo real. Combínalo con la tabla de arriba: la coalescencia nula mantiene honesto el acumulador en las páginas que no encontraron nada, y el while mantiene vivo el bucle más allá de ellas.
  • #filter0 no es decoración. Year está en la lista de palabras reservadas de AWS, y usarlo sin alias devuelve ValidationException: Invalid FilterExpression: Attribute name is a reserved keyword; reserved keyword: Year.
  • Limit cuenta Items leídos, no Items devueltos. Con este filtro, Limit: 10 da Count: 0 y ScannedCount: 10. Es un mando para amortiguar picos de capacidad, no una forma de pedir diez resultados.
  • Segment / TotalSegments reparten un scan de tabla completa entre varios workers. Eso divide el tiempo de reloj, no el coste — se gastan las mismas 284,5 unidades, solo que más rápido y con más concurrencia.

Lo que eso cuesta en una tabla real

284,5 unidades de lectura para 8 Items es la forma del problema, y escala linealmente con la tabla, no con el resultado. Antes de llevar a producción un scan con filtro en un camino crítico, ponle precio a la lectura de la tabla completa con tu tamaño de Item y tu tráfico en la calculadora de precios de DynamoDB, y compáralo con un GSI que convierta ese mismo patrón de acceso en un Query.

Para explorar tablas en una GUI, con cuadrículas de resultados filtradas y paginadas, descarga DynoTable en vez de escanear a ciegas desde un script.

Guías relacionadas

Referencias

Construye esta solicitud visualmente

Compón esta operación en el Generador de consultas de DynamoDB gratuito —condición de clave, filtro, índice, Limit, orden de clasificación y un bucle de paginación— y cópiala de vuelta como un programa ejecutable para SDK v3, CLI o boto3.

Abrir el Generador de consultas de DynamoDB

Trabaja con DynamoDB sin la Consola

Un cliente de escritorio rápido para DynamoDB que ejecuta el SQL real que DynamoDB no puede — JOINs, GROUP BY, agregaciones — con edición visual y un agente de IA con tus propias claves de Bedrock.

Prueba gratuita de 30 días, sin tarjeta — después, el plan Free sin límite de tiempo.