DYNAMODB_QUERY - Buscar Múltiplos Itens por Partition Key
O que é este Node?
O DYNAMODB_QUERY é o node responsável por buscar múltiplos itens de uma tabela DynamoDB usando a Partition Key, opcionalmente filtrando pela Sort Key e outros atributos.
Por que este Node existe?
Query é a operação mais eficiente para buscar conjuntos de dados relacionados no DynamoDB. O DYNAMODB_QUERY existe para:
- Performance: Busca apenas na partição específica (não escaneia a tabela inteira)
- Relacionamentos: Recupera todos os itens de um usuário, pedidos de uma data, etc.
- Ordenação: Retorna itens ordenados pela Sort Key automaticamente
- Filtros: Permite condições adicionais sem carregar dados desnecessários
Como funciona internamente?
Quando o DYNAMODB_QUERY é executado, o sistema:
- Autentica: Valida as credenciais AWS
- Monta Expressão: Cria KeyConditionExpression com Partition Key (obrigatório) e Sort Key (opcional)
- Localiza Partição: Vai direto para a partição específica (não escaneia toda tabela)
- Filtra: Aplica Sort Key e FilterExpression se fornecidos
- Ordena: Retorna itens ordenados pela Sort Key (crescente por padrão)
- Limita: Aplica limite de itens se especificado
- Retorna: Array de itens encontrados + contagem
Código interno (aws-executors.service.ts:313-324):
case 'query':
const queryResult = await dynamodb.query({
TableName: data.tableName,
KeyConditionExpression: data.keyConditionExpression,
ExpressionAttributeValues: data.expressionAttributeValues,
Limit: data.limit,
}).promise();
return {
success: true,
items: queryResult.Items,
count: queryResult.Count,
};
Quando você DEVE usar este Node?
Use DYNAMODB_QUERY sempre que precisar de buscar múltiplos itens relacionados:
Casos de uso
- Histórico do usuário: "Buscar todos os pedidos de um cliente específico"
- Timeline: "Listar todas as mensagens de um chat nos últimos 7 dias"
- Ranking: "Top 10 produtos mais vendidos em uma categoria"
- Logs filtrados: "Buscar erros de uma aplicação em determinado período"
Quando NÃO usar DYNAMODB_QUERY
- Buscar item único por chave: Use DYNAMODB_GET ao invés (mais eficiente)
- Buscar sem Partition Key: Use DYNAMODB_SCAN (porém é lento e caro)
- Buscar em múltiplas partições: Use DYNAMODB_SCAN ou múltiplos Query
- Buscar por atributo não-chave sem índice: Use DYNAMODB_SCAN
Parâmetros Detalhados
accessKeyId (string, obrigatório)
O que é: Chave de acesso da AWS para autenticação.
Padrão: Nenhum (sempre obrigatório)
Flow completo para testar:
{
"name": "Teste DynamoDB Query - Access Key",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 250, "y": 100 },
"data": {
"label": "User ID",
"parameters": {
"message": "Digite seu ID para buscar pedidos:",
"variableName": "user_id"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_query",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Buscar Pedidos",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "query",
"tableName": "Pedidos",
"keyConditionExpression": "userId = :uid",
"expressionAttributeValues": {
":uid": "{{user_id}}"
}
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 550, "y": 100 },
"data": {
"label": "Resultado",
"parameters": {
"message": "Encontrados {{dynamodb_1.count}} pedidos"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Digite um ID de usuário. Verá quantos pedidos esse usuário tem.
secretAccessKey (string, obrigatório)
O que é: Chave secreta da AWS.
Padrão: Nenhum (sempre obrigatório)
Flow completo para testar:
{
"name": "Teste DynamoDB Query - Secret Key",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 250, "y": 100 },
"data": {
"label": "Categoria",
"parameters": {
"message": "Digite a categoria do produto:",
"variableName": "category"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_query",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Buscar Produtos",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "sa-east-1",
"operation": "query",
"tableName": "Produtos",
"keyConditionExpression": "categoria = :cat",
"expressionAttributeValues": {
":cat": "{{category}}"
}
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 550, "y": 100 },
"data": {
"label": "Resultado",
"parameters": {
"message": "{{dynamodb_1.count}} produtos na categoria {{category}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Digite nome de categoria. Verá quantos produtos existem nela.
region (string, obrigatório)
O que é: Região AWS da tabela DynamoDB.
Padrão: Nenhum (sempre obrigatório)
Flow completo para testar:
{
"name": "Teste DynamoDB Query - Region",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 150 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 250, "y": 150 },
"data": {
"label": "Store ID",
"parameters": {
"message": "Digite o ID da loja:",
"variableName": "store_id"
}
}
},
{
"id": "switch_1",
"type": "switch",
"position": { "x": 400, "y": 150 },
"data": {
"label": "Escolher Região",
"parameters": {
"message": "Região da loja?\n1️⃣ US\n2️⃣ Brasil",
"cases": [
{ "value": "1", "label": "US" },
{ "value": "2", "label": "BR" }
]
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_query",
"position": { "x": 550, "y": 100 },
"data": {
"label": "Query US",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "query",
"tableName": "Vendas",
"keyConditionExpression": "storeId = :sid",
"expressionAttributeValues": {
":sid": "{{store_id}}"
}
}
}
},
{
"id": "dynamodb_2",
"type": "dynamodb_query",
"position": { "x": 550, "y": 200 },
"data": {
"label": "Query BR",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "sa-east-1",
"operation": "query",
"tableName": "Vendas",
"keyConditionExpression": "storeId = :sid",
"expressionAttributeValues": {
":sid": "{{store_id}}"
}
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 150 },
"data": {
"label": "Resultado",
"parameters": {
"message": "Vendas encontradas na região selecionada"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 850, "y": 150 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "switch_1" },
{ "source": "switch_1", "target": "dynamodb_1", "label": "1" },
{ "source": "switch_1", "target": "dynamodb_2", "label": "2" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "dynamodb_2", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Escolha região. Query busca apenas naquela região específica.
tableName (string, obrigatório)
O que é: Nome da tabela DynamoDB onde buscar.
Padrão: Nenhum (sempre obrigatório)
Flow completo para testar:
{
"name": "Teste DynamoDB Query - Table Name",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 250, "y": 100 },
"data": {
"label": "Tabela",
"parameters": {
"message": "Nome da tabela:",
"variableName": "table_name"
}
}
},
{
"id": "input_2",
"type": "input",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Partition Key",
"parameters": {
"message": "Valor da Partition Key:",
"variableName": "pk_value"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_query",
"position": { "x": 550, "y": 100 },
"data": {
"label": "Query Dinâmica",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "query",
"tableName": "{{table_name}}",
"keyConditionExpression": "pk = :pkval",
"expressionAttributeValues": {
":pkval": "{{pk_value}}"
}
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Resultado",
"parameters": {
"message": "Query executada em {{table_name}}: {{dynamodb_1.count}} itens"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 850, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "input_2" },
{ "source": "input_2", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Digite nome de tabela e valor. Se tabela não existir, erro "ResourceNotFoundException".
keyConditionExpression (string, obrigatório)
O que é: Expressão que define a busca. DEVE incluir Partition Key. Pode incluir Sort Key.
Padrão: Nenhum (sempre obrigatório)
Sintaxe:
- Partition Key apenas: userId = :uid
- Com Sort Key (igual): userId = :uid AND timestamp = :ts
- Com Sort Key (range): userId = :uid AND timestamp BETWEEN :start AND :end
- Operadores Sort Key: =, <, <=, >, >=, BETWEEN, begins_with()
Flow completo para testar:
{
"name": "Teste DynamoDB Query - Key Condition",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 200 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 250, "y": 200 },
"data": {
"label": "User ID",
"parameters": {
"message": "Digite seu ID:",
"variableName": "user_id"
}
}
},
{
"id": "switch_1",
"type": "switch",
"position": { "x": 400, "y": 200 },
"data": {
"label": "Filtro",
"parameters": {
"message": "Buscar pedidos:\n1️⃣ Todos\n2️⃣ Últimos 7 dias\n3️⃣ 2025",
"cases": [
{ "value": "1", "label": "Todos" },
{ "value": "2", "label": "7 dias" },
{ "value": "3", "label": "2025" }
]
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_query",
"position": { "x": 550, "y": 150 },
"data": {
"label": "Query Todos",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "query",
"tableName": "Pedidos",
"keyConditionExpression": "userId = :uid",
"expressionAttributeValues": {
":uid": "{{user_id}}"
}
}
}
},
{
"id": "dynamodb_2",
"type": "dynamodb_query",
"position": { "x": 550, "y": 250 },
"data": {
"label": "Query Recentes",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "query",
"tableName": "Pedidos",
"keyConditionExpression": "userId = :uid AND createdAt > :weekAgo",
"expressionAttributeValues": {
":uid": "{{user_id}}",
":weekAgo": "2025-10-05"
}
}
}
},
{
"id": "dynamodb_3",
"type": "dynamodb_query",
"position": { "x": 550, "y": 350 },
"data": {
"label": "Query 2025",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "query",
"tableName": "Pedidos",
"keyConditionExpression": "userId = :uid AND begins_with(createdAt, :year)",
"expressionAttributeValues": {
":uid": "{{user_id}}",
":year": "2025"
}
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 250 },
"data": {
"label": "Resultado",
"parameters": {
"message": "Pedidos encontrados conforme filtro selecionado"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 850, "y": 250 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "switch_1" },
{ "source": "switch_1", "target": "dynamodb_1", "label": "1" },
{ "source": "switch_1", "target": "dynamodb_2", "label": "2" },
{ "source": "switch_1", "target": "dynamodb_3", "label": "3" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "dynamodb_2", "target": "message_1" },
{ "source": "dynamodb_3", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Escolha filtro. Cada opção usa KeyConditionExpression diferente.
expressionAttributeValues (object, obrigatório)
O que é: Valores das variáveis usadas na KeyConditionExpression. Formato: { ":variavel": "valor" }
Padrão: Nenhum (sempre obrigatório quando há placeholders)
Flow completo para testar:
{
"name": "Teste DynamoDB Query - Expression Attribute Values",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 150 },
"data": { "label": "Início" }
},
{
"id": "email_1",
"type": "email",
"position": { "x": 250, "y": 150 },
"data": {
"label": "Email",
"parameters": {
"message": "Digite seu email:",
"variableName": "user_email"
}
}
},
{
"id": "date_1",
"type": "date",
"position": { "x": 400, "y": 150 },
"data": {
"label": "Data Início",
"parameters": {
"message": "Data inicial (DD/MM/AAAA):",
"variableName": "start_date"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_query",
"position": { "x": 550, "y": 150 },
"data": {
"label": "Buscar Atividades",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "query",
"tableName": "Atividades",
"keyConditionExpression": "email = :e AND dataAtividade >= :d",
"expressionAttributeValues": {
":e": "{{user_email}}",
":d": "{{start_date}}"
}
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 150 },
"data": {
"label": "Resultado",
"parameters": {
"message": "{{dynamodb_1.count}} atividades desde {{start_date}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 850, "y": 150 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "email_1" },
{ "source": "email_1", "target": "date_1" },
{ "source": "date_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Digite email e data. Os valores são substituídos nos placeholders da expressão.
limit (number, opcional)
O que é: Número máximo de itens a retornar. Útil para paginação e controle de custos.
Padrão: Sem limite (retorna todos até 1MB de dados)
Flow completo para testar:
{
"name": "Teste DynamoDB Query - Limit",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 250, "y": 100 },
"data": {
"label": "User ID",
"parameters": {
"message": "Digite seu ID:",
"variableName": "user_id"
}
}
},
{
"id": "number_1",
"type": "number",
"position": { "x": 400, "y": 100 },
"data": {
"label": "Limite",
"parameters": {
"message": "Quantos itens mostrar? (1-100)",
"variableName": "item_limit"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_query",
"position": { "x": 550, "y": 100 },
"data": {
"label": "Query com Limite",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "query",
"tableName": "Historico",
"keyConditionExpression": "userId = :uid",
"expressionAttributeValues": {
":uid": "{{user_id}}"
},
"limit": "{{item_limit}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Resultado",
"parameters": {
"message": "Mostrando {{dynamodb_1.count}} de seus registros (limite: {{item_limit}})"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 850, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "number_1" },
{ "source": "number_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Digite um número. Apenas aquela quantidade de itens será retornada.
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| accessKeyId | string | Sim | Chave de acesso AWS |
| secretAccessKey | string | Sim | Chave secreta AWS |
| region | string | Sim | Região AWS (ex: us-east-1) |
| operation | string | Sim | Tipo de operação (sempre "query") |
| tableName | string | Sim | Nome da tabela DynamoDB |
| keyConditionExpression | string | Sim | Expressão de busca (DEVE ter Partition Key) |
| expressionAttributeValues | object | Sim | Valores dos placeholders da expressão |
| limit | number | Não | Máximo de itens a retornar |
Exemplo 1: Histórico de Pedidos do Cliente
Objetivo: Demonstrar busca de todos os pedidos de um cliente específico, ordenados por data.
JSON para Importar
{
"name": "Histórico de Pedidos - Query",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 200 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 250, "y": 200 },
"data": {
"label": "Boas-vindas",
"parameters": {
"message": "📦 Consulta de Pedidos\n\nVamos buscar seu histórico."
}
}
},
{
"id": "email_1",
"type": "email",
"position": { "x": 400, "y": 200 },
"data": {
"label": "Email",
"parameters": {
"message": "Digite seu email:",
"variableName": "customer_email"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_query",
"position": { "x": 550, "y": 200 },
"data": {
"label": "Buscar Pedidos",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "sa-east-1",
"operation": "query",
"tableName": "Pedidos",
"keyConditionExpression": "customerEmail = :email",
"expressionAttributeValues": {
":email": "{{customer_email}}"
},
"limit": 10
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 700, "y": 200 },
"data": {
"label": "Tem Pedidos?",
"parameters": {
"variable": "{{dynamodb_1.count}}",
"operator": ">",
"value": "0"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 850, "y": 150 },
"data": {
"label": "Mostrar Pedidos",
"parameters": {
"message": "📋 Seus Pedidos (últimos 10):\n\nTotal: {{dynamodb_1.count}} pedidos\n\n{{#each dynamodb_1.items}}\n🆔 {{this.pedidoId}}\n📅 {{this.data}}\n💰 R$ {{this.valorTotal}}\n📊 Status: {{this.status}}\n---\n{{/each}}"
}
}
},
{
"id": "message_3",
"type": "message",
"position": { "x": 850, "y": 250 },
"data": {
"label": "Sem Pedidos",
"parameters": {
"message": "📭 Você ainda não tem pedidos.\n\nQue tal fazer seu primeiro pedido?"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1000, "y": 200 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "email_1" },
{ "source": "email_1", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "condition_1" },
{ "source": "condition_1", "target": "message_2", "label": "true" },
{ "source": "condition_1", "target": "message_3", "label": "false" },
{ "source": "message_2", "target": "end_1" },
{ "source": "message_3", "target": "end_1" }
]
}
Saída esperada:
Sistema: 📦 Consulta de Pedidos
Vamos buscar seu histórico.
Sistema: Digite seu email:
Usuário: jose@example.com
Sistema: 📋 Seus Pedidos (últimos 10):
Total: 3 pedidos
🆔 PED-001
📅 2025-10-01
💰 R$ 299.90
📊 Status: entregue
---
🆔 PED-002
📅 2025-10-05
💰 R$ 1499.00
📊 Status: em trânsito
---
🆔 PED-003
📅 2025-10-10
💰 R$ 89.90
📊 Status: processando
---
Exemplo 2: Mensagens de Chat por Período
Objetivo: Demonstrar Query com Sort Key range (BETWEEN) para buscar mensagens em intervalo de datas.
JSON para Importar
{
"name": "Mensagens de Chat por Período - Query BETWEEN",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 250 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 250, "y": 250 },
"data": {
"label": "Iniciar",
"parameters": {
"message": "💬 Histórico de Chat\n\nBuscar mensagens por período."
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 400, "y": 250 },
"data": {
"label": "Chat ID",
"parameters": {
"message": "Digite o ID do chat:",
"variableName": "chat_id"
}
}
},
{
"id": "date_1",
"type": "date",
"position": { "x": 550, "y": 200 },
"data": {
"label": "Data Início",
"parameters": {
"message": "Data inicial (DD/MM/AAAA):",
"variableName": "start_date"
}
}
},
{
"id": "date_2",
"type": "date",
"position": { "x": 550, "y": 300 },
"data": {
"label": "Data Fim",
"parameters": {
"message": "Data final (DD/MM/AAAA):",
"variableName": "end_date"
}
}
},
{
"id": "dynamodb_1",
"type": "dynamodb_query",
"position": { "x": 700, "y": 250 },
"data": {
"label": "Query Mensagens",
"parameters": {
"accessKeyId": "AKIAIOSFODNN7EXAMPLE",
"secretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"region": "us-east-1",
"operation": "query",
"tableName": "ChatMensagens",
"keyConditionExpression": "chatId = :cid AND timestamp BETWEEN :start AND :end",
"expressionAttributeValues": {
":cid": "{{chat_id}}",
":start": "{{start_date}}T00:00:00Z",
":end": "{{end_date}}T23:59:59Z"
}
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 850, "y": 250 },
"data": {
"label": "Mostrar Resultado",
"parameters": {
"message": "💬 Mensagens Encontradas: {{dynamodb_1.count}}\n\n📅 Período: {{start_date}} a {{end_date}}\n\n{{#each dynamodb_1.items}}\n⏰ {{this.timestamp}}\n👤 {{this.remetente}}: {{this.mensagem}}\n---\n{{/each}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1000, "y": 250 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "input_1" },
{ "source": "input_1", "target": "date_1" },
{ "source": "date_1", "target": "date_2" },
{ "source": "date_2", "target": "dynamodb_1" },
{ "source": "dynamodb_1", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Saída esperada:
Sistema: 💬 Histórico de Chat
Buscar mensagens por período.
Sistema: Digite o ID do chat:
Usuário: chat_12345
Sistema: Data inicial (DD/MM/AAAA):
Usuário: 01/10/2025
Sistema: Data final (DD/MM/AAAA):
Usuário: 10/10/2025
Sistema: 💬 Mensagens Encontradas: 15
📅 Período: 01/10/2025 a 10/10/2025
⏰ 2025-10-01T10:30:00Z
👤 João: Olá, tudo bem?
---
⏰ 2025-10-01T10:31:15Z
👤 Maria: Oi! Tudo sim, e você?
---
⏰ 2025-10-05T14:22:00Z
👤 João: Quando podemos nos reunir?
---
Resposta do Node
{
"success": true,
"items": [
{
"userId": "user123",
"pedidoId": "PED-001",
"data": "2025-10-01",
"valorTotal": 299.90,
"status": "entregue"
},
{
"userId": "user123",
"pedidoId": "PED-002",
"data": "2025-10-05",
"valorTotal": 1499.00,
"status": "em trânsito"
}
],
"count": 2
}
Diferença: Query vs Scan
QUERY (Recomendado)
- Performance: Rápido - busca apenas em 1 partição
- Custo: Baixo - paga apenas pelos itens lidos
- Requisito: DEVE ter Partition Key na condição
- Ordenação: Automática pela Sort Key
- Uso: Quando você sabe a Partition Key
SCAN (Evitar quando possível)
- Performance: Lento - lê TODA a tabela
- Custo: Alto - paga por TODOS os itens escaneados
- Requisito: Nenhum - busca em toda tabela
- Ordenação: Nenhuma garantia
- Uso: Quando NÃO sabe a Partition Key ou precisa de todos os dados
Exemplo de custo: - Tabela com 1 milhão de itens - Query: Lê 10 itens da partição = $0.000001 - Scan: Lê 1 milhão de itens = $0.10 (100.000x mais caro!)
Boas Práticas
✅ SIM:
- SEMPRE use Query ao invés de Scan quando souber a Partition Key
- Use
limitpara controlar quantidade de dados retornados - Crie GSI (Global Secondary Index) para queries em outros atributos
- Use
begins_with()para buscar prefixos (ex: ano "2025") - Combine Partition Key + Sort Key range para buscas precisas
- Ordene resultados aproveitando a Sort Key
❌ NÃO:
- Fazer Query sem Partition Key (use Scan ou crie GSI)
- Buscar em múltiplas partições com um Query (faça múltiplos Queries)
- Retornar milhares de itens sem paginação (use
limit) - Usar FilterExpression quando Sort Key pode fazer o filtro (menos eficiente)
- Assumir que Query retorna TODOS os itens (DynamoDB limita a 1MB por request)
Dicas
💡 Dica 1: Query retorna itens ordenados pela Sort Key. Use isso ao seu favor: timestamps como Sort Key dão timeline automática!
💡 Dica 2: begins_with() é perfeito para hierarquias: begins_with(categoria, "Eletrônicos/") encontra "Eletrônicos/TV", "Eletrônicos/Notebook", etc.
💡 Dica 3: Query pode retornar até 1MB de dados por request. Para mais, implemente paginação usando LastEvaluatedKey.
💡 Dica 4: Se você faz Query frequente em atributo não-chave, crie GSI (Global Secondary Index). Transforma atributo comum em Partition Key para queries rápidas.
💡 Dica 5: Use ScanIndexForward: false (no código) para inverter ordem da Sort Key (do mais recente para o mais antigo).
Próximo Node
→ DYNAMODB_GET - Buscar item único por chave → DYNAMODB_SCAN - Escanear tabela inteira com filtros → DYNAMODB_UPDATE - Atualizar campos específicos