BatchGetItem do DynamoDB em Node.js (AWS SDK v3)
O BatchGetItem busca até 100 itens por chave primária em uma requisição. No AWS SDK v3 a chamada precisa ser um laço, porque UnprocessedKeys chega em uma resposta bem-sucedida, e não em um erro. O que preenche esse campo, e por que 16 MB e 1 MB por partição são os números que importam, está em operações em lote no DynamoDB. Esta página é sobre a chamada v3 e sobre o que ela devolve.
Código
import {BatchGetItemCommand, DynamoDBClient} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
let requestItems = {
Music: {
Keys: [
{Artist: {S: 'Arturo Sandoval'}, SongTitle: {S: 'Cubano Chant'}},
{Artist: {S: 'Arturo Sandoval'}, SongTitle: {S: 'A Mis Abuelos'}},
{Artist: {S: 'Ella Fitzgerald'}, SongTitle: {S: 'Misty'}}
]
}
};
const items = [];
let attempt = 0;
do {
const response = await client.send(new BatchGetItemCommand({RequestItems: requestItems}));
items.push(...(response.Responses?.Music ?? []));
// A partial result is NOT an error: throttling, a >16 MB response, or an
// internal failure returns the leftovers in UnprocessedKeys. Retry them
// with exponential backoff.
requestItems = response.UnprocessedKeys;
if (requestItems && Object.keys(requestItems).length > 0) {
attempt += 1;
await sleep(Math.min(100 * 2 ** attempt, 5000));
}
} while (requestItems && Object.keys(requestItems).length > 0);
console.log(`Fetched ${items.length} items`);Explicação
- O encadeamento opcional não é ruído defensivo.
ResponseseUnprocessedKeyssão ambos opcionais nos tipos da v3, entãoresponse.Responses?.Music ?? []e a guarda comObject.keys()são o que o compilador exige. Em JavaScript puro, são o que impede a primeira resposta vazia de lançar erro. - Ramifique com base em
err.name. A v3 coloca ali o código de erro do serviço, e as duas falhas que este comando de fato gera não são retentáveis, então elas nunca podem cair no laço de backoff. Mais de 100 chaves dãoValidationException/Too many items requested for the BatchGetItem call; a mesma chave duas vezes dáProvided list of item keys contains duplicates. Ambas estão reproduzidas literalmente na página de Python. UnprocessedKeysjá chega no formato deRequestItems, que é a única razão pela qual o laço consegue reatribuí-lo direto. Não é um cursor de paginação e não significa que a chamada falhou.- O backoff é uma instrução da AWS, não um capricho. A referência da API manda usar "an exponential backoff algorithm" porque um retry imediato cai na mesma partição com throttle.
ConsistentReadeProjectionExpressionsão por tabela, definidos dentro de cada entrada deRequestItemse não no nível superior. Isso é fácil de deixar passar quando o mapa tem uma chave só e parece uma requisição plana.
Como a resposta volta de fato
Rode o bloco acima no DynamoDB Local 3.3.0 com as três músicas presentes, acrescente ReturnConsumedCapacity: 'TOTAL' e imprima os títulos das músicas em vez da contagem:
order: [ 'A Mis Abuelos', 'Misty', 'Cubano Chant' ]
UnprocessedKeys: {}
ConsumedCapacity: [ { TableName: 'Music', CapacityUnits: 1.5 } ]A requisição listou Cubano Chant, A Mis Abuelos, Misty. A resposta não está em nenhuma dessas posições, e é por isso que o laço empurra tudo para um array plano em vez de indexar por posição. Case os itens de volta com as requisições pelos atributos de chave, e inclua essas chaves em qualquer ProjectionExpression para você ainda ter algo com que casar.
Defina ConsistentRead: true nessa mesma entrada de Music e as mesmas três chaves custam 3 unidades em vez de 1,5. Três itens abaixo de 4 KB cada são cobrados como três leituras GetItem separadas, a meia unidade com consistência eventual e uma unidade inteira com consistência forte. A calculadora de preços converte essa aritmética por item em um número mensal antes de você se comprometer com um padrão de leitura.
Agora apague Misty e rode de novo: dois itens, um UnprocessedKeys vazio e 1,0 unidade. A chave ausente não foi cobrada. Isso é um artefato do DynamoDB Local, não o contrato; a referência do BatchGetItem (consultada em 2026-07-28) diz que requisições de itens inexistentes consomem a capacidade de leitura mínima para o tipo de leitura. Não dimensione um lote de cache misses a partir de uma execução local.
Para puxar um conjunto de chaves de volta e olhar o que realmente retornou, sem antes escrever o laço, baixe o DynoTable.
Exemplos relacionados
- BatchGetItem do DynamoDB em Python — a mesma leitura em lote com boto3.
- BatchGetItem do DynamoDB com a AWS CLI — a mesma leitura em lote a partir do shell.
- GetItem do DynamoDB em Node.js — a leitura de item único que isto agrupa.
- Operações em lote no DynamoDB — limites, falha parcial e quando o lote compensa.
- "Too many items requested for the BatchGetItem call" — mais de 100 chaves em uma requisição.
- "Provided list of item keys contains duplicates" — a mesma chave duas vezes em um lote.
Referências
- BatchGetItem — Amazon DynamoDB API Reference
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
Verificado pela última vez em 2026-07-28 contra a documentação oficial da AWS vinculada acima.