Módulo 3: Loops e Iteraciones

Aggregate: Juntar Resultados

Descripción de la cápsula

Iteración (implícita o explícita) procesa N items independientemente — cada uno con su propia ejecución. Pero a veces necesitas el resultado combinado al final: un mensaje resumen con todos los items, un reporte con todas las filas procesadas, un único request a una API que acepta batch. Aggregate es el nodo que colapsa N items en 1 con los datos juntados.

En esta cápsula vas a aprender los modos de Aggregate, los casos típicos de uso (resumen, batch request, transformación a array), las decisiones de diseño (cuándo aggregate vs procesamiento individual), y las trampas al combinar Aggregate con SplitInBatches.


Lo que vas a aprender

Al terminar esta cápsula serás capaz de:

  • Entender qué hace Aggregate y cuándo aplicarlo
  • Configurar los modos principales
  • Aplicar a 4 casos típicos comunes
  • Combinar con SplitInBatches correctamente
  • Decidir cuándo aggregate vs no según necesidad

El modelo: de N items a 1

Aggregate convierte N items en 1 item con un campo que es un array con los N items originales.

Antes:

[
  { name: "Mike", amount: 100 },
  { name: "Ana",  amount: 200 },
  { name: "Luis", amount: 150 }
]

Después de Aggregate:

[
  {
    all_items: [
      { name: "Mike", amount: 100 },
      { name: "Ana",  amount: 200 },
      { name: "Luis", amount: 150 }
    ]
  }
]

Un solo item, con un array all_items adentro que contiene los N originales.


Configuración del Aggregate node

Modo principal: Aggregate All Item Data

  • Aggregate: All Item Data (Into a Single List)
  • Put Output in Field: nombre del campo donde se guarda el array (default data o aggregated)

Modo: Individual Fields

Para aggregar campos específicos:

  • Aggregate: Individual Fields
  • Field to Aggregate: ej. email
  • Output: { "email": ["a@x.com", "b@y.com", "c@z.com"] } — array solo de emails

Modo: All Item Data with Field

Combinación: keep all data + algunos campos extraídos como arrays.


Caso 1: Resumen / reporte agregado

Caso: procesar 50 leads, mandar 1 mensaje a Slack con la lista completa, no 50 mensajes.

[Sheet: 50 leads]
   │
[Set: agregar processed_at]
   │
[Aggregate: all data into 'leads_list']
   │
[Slack: send 1 message]
  Mensaje:
  📊 *Reporte de leads del día*
  Total: {{ $json.leads_list.length }}

  {{ $json.leads_list.map(l => '• ' + l.name + ' (' + l.email + ')').join('\n') }}

Resultado: 1 mensaje en Slack con la lista de los 50 leads.


Caso 2: Batch API request

Caso: una API acepta batch creation (recibir array, crear N registros en 1 request).

[N leads]
   │
[Aggregate: emails into 'emails_array']
   │
[HTTP POST: { "emails": $json.emails_array }]

1 request en vez de N. Más eficiente y respetuoso con rate limits.


Caso 3: Transformación a CSV/JSON único

Caso: quieres exportar items a un archivo CSV o JSON.

[N items]
   │
[Aggregate: all data]
   │
[Code o Function: convertir array a CSV string]
   │
[Write File / Send Email con attachment]

Caso 4: Calcular total / estadísticas

Caso: sumar el monto total de N pedidos.

[N pedidos]
   │
[Aggregate: amounts into 'amounts']
   │
[Set:]
  total: {{ $json.amounts.reduce((a,b) => a+b, 0) }}
  average: {{ $json.amounts.reduce((a,b) => a+b, 0) / $json.amounts.length }}
  max: {{ Math.max(...$json.amounts) }}

Aggregate dentro de SplitInBatches (cuidado)

Si tienes:

[SplitInBatches batch=10]
   │
[procesa cada batch]
   │
[Aggregate dentro del loop?]

Cuidado: Aggregate solo "ve" los items del batch actual. Si quieres aggregate del total, debes hacerlo:

Opción A: Aggregate después del loop (Done branch)

[SplitInBatches] → [procesa] → [guarda resultado parcial en Sheet]
                       │
                       └─→ loop
                       │
                       ↓
                    [Done]
                       │
                    [Lee Sheet con todos los resultados]
                       │
                    [Aggregate global]
                       │
                    [reporte final]

Cada batch guarda resultados parciales. Al final del loop, lees todos los parciales y haces Aggregate.

Opción B: Aggregate en cada batch + acumulador

Más complejo — mantener un estado entre batches. Generalmente no vale la pena vs opción A.


Decisión: ¿aggregate o no?

Aggregate cuando:

  • Necesitas 1 resultado / mensaje / request con todos los items
  • API acepta batch (1 request con array vs N requests)
  • Reportes / resúmenes
  • Cálculos sobre el set completo (total, promedio)

NO aggregate cuando:

  • Cada item necesita procesamiento independiente (mandar email a cada uno)
  • Items van a destinos distintos (Switch por categoría)
  • Volumen muy alto (Aggregate carga todo en memoria — puede ser issue con miles de items)

Operaciones útiles sobre arrays agregados

Una vez que tienes el array, puedes manipularlo:

// Filtrar
$json.items.filter(i => i.active)

// Map (extraer campo)
$json.items.map(i => i.email)

// Sumar
$json.items.reduce((a, b) => a + b.amount, 0)

// Group by (manual)
{{
  $json.items.reduce((acc, item) => {
    if (!acc[item.category]) acc[item.category] = [];
    acc[item.category].push(item);
    return acc;
  }, {})
}}

// Sort
$json.items.sort((a, b) => b.amount - a.amount)  // descendente por monto

// Top N
$json.items.sort(...).slice(0, 10)  // top 10

Trampas comunes

Trampa 1: Aggregate cuando querías iteración

Qué pasa: Aggregate antes de Slack. Esperabas 1 mensaje por item — recibes 1 con la lista. O viceversa.

Cómo evitar: Pensar antes: ¿necesitas N notificaciones (uno por item) o 1 resumen?


Trampa 2: Aggregate después de operación costosa

Qué pasa: Procesas 1000 items con API (cara). Después Aggregate. Pero solo querías estadísticas — no necesitabas procesar todos individualmente.

Cómo evitar: Aggregate temprano si vas a hacer cálculos sobre el set, no individual.


Trampa 3: Confundir cómo se ve el output

Qué pasa: Después del Aggregate, esperabas seguir usando $json.email como antes. Ahora necesitas $json.items[0].email.

Cómo evitar: Inspeccionar el output del Aggregate (vista Schema, G1-M06-03) para ver la estructura nueva.


Trampa 4: Aggregate con datos heterogéneos

Qué pasa: Tu input tiene items con structuras distintas. Aggregate junta todos pero el array resultante es difícil de procesar.

Cómo evitar: Normalizar antes de Aggregate. Set previo que da estructura uniforme a todos los items.


Trampa 5: Aggregate con miles de items y memoria limitada

Qué pasa: Aggregate de 10,000 items grandes (cada uno con binary o muchos campos). Memoria de n8n se satura.

Cómo evitar:

  • Para volumen masivo, procesar en batches y guardar resultados parciales en DB/Sheet
  • Aggregate solo si memoria razonable

Aggregate vs Merge

Quizás te preguntes la diferencia:

AggregateMerge
Toma 1 input con N itemsToma 2+ inputs con items separados
Colapsa N items en 1Combina items de diferentes streams
Resultado: 1 item con arrayResultado: combinación según modo
Caso: resumen de itemsCaso: unir Sheet con CRM API

No son intercambiables. Cada uno para su caso.


Ejemplo completo: reporte de leads diario

[Schedule: 6am diario]
   │
[Sheet: leads del día]
   │
[Filter: válidos]
   │
[Set: enriquecer con score]
   │
[Aggregate: all data into 'leads']
   │
[Set: calcular stats]
  total: {{ $json.leads.length }}
  total_amount: {{ $json.leads.reduce((a, b) => a + Number(b.amount), 0) }}
  top_3: {{ $json.leads.sort((a, b) => b.score - a.score).slice(0, 3) }}
   │
[Slack: reporte]
  📊 *Reporte diario*
  Total leads: {{ $json.total }}
  Valor total: ${{ $json.total_amount }}

  *Top 3:*
  {{ $json.top_3.map((l, i) => (i+1) + '. ' + l.name + ' (score: ' + l.score + ')').join('\n') }}

Resultado: 1 mensaje diario con stats y top 3, en lugar de 50 mensajes individuales.


Ejercicio: refactorizar a Aggregate

Objetivo: practicar identificar oportunidades.

Workflow original

[Sheet: 100 pedidos del día]
   │
[Slack: enviar mensaje por cada pedido]

100 mensajes saturando el canal.

Tu tarea

Refactoriza a:

  • 1 mensaje resumen con stats
  • Total de pedidos
  • Monto total
  • Top 5 por monto
Solución
[Sheet: 100 pedidos]
   │
[Aggregate: all into 'orders']
   │
[Set:]
  - total: $json.orders.length
  - total_amount: $json.orders.reduce((a,b) => a + Number(b.amount), 0)
  - top_5: $json.orders.sort((a,b) => b.amount - a.amount).slice(0, 5)
   │
[Slack: 1 mensaje]

100 mensajes → 1.


Resumen y siguiente paso

  • Aggregate colapsa N items en 1 con array adentro
  • Modos: all data, individual fields, all + field
  • 4 casos típicos: resumen, batch API, transformación, estadísticas
  • Aggregate + SplitInBatches: Aggregate al final del loop (Done branch), no dentro
  • Aggregate vs Merge: distintas operaciones, no intercambiables
  • 5 trampas: aggregate cuando querías iteración, después de procesamiento costoso, confundir estructura, datos heterogéneos, memoria con miles

Antes de avanzar deberías poder:

  • Decidir cuándo Aggregate vs iteración individual
  • Acceder a campos del array agregado
  • Hacer cálculos sobre el array (sum, top N, etc.)

Lo que sigue (cápsula 07):

Loops complejos: paginación de APIs (real, no simplificada), retry strategies sofisticadas, loops con condiciones de salida dinámicas. Los patrones que aparecen en integraciones reales.


Recursos adicionales

  1. Aggregate Node Documentation - Referencia.
  2. Array Methods (MDN) - map, filter, reduce, etc.

Creado: Mayo 11, 2026 Versión: 1.0