В n8n три заказа обычно приходят как три отдельных items. Но для одного JSON-документа часто нужен объект с массивом orders внутри. Aggregate собирает такой массив штатным узлом. Сделаем пример, который сохранит связь полей каждого заказа и проверит, что в результат не попали служебные данные.
Результат инструкции
Workflow ezGPT - Aggregate Orders превращает три items в один item с orders из трёх объектов. У каждого остаются его ID, клиент, сумма и примечание, если оно было. Сумма 0 сохраняется числом; явное null не превращается в отсутствующее поле. internal_note в итоговый JSON не включается.
В конце Check Payload проверит структуру, количество, порядок и значения, затем добавит count 3 и сумму 199900 копеек, или 1999 рублей. Эти счётчики считает наш Code, не сам Aggregate. Внешнего API и AI-модели здесь нет; action_performed false. Полученный JSON — учебная структура, а не универсальный формат любого API.
Что понадобится
- Работающий n8n и права создать отдельный workflow. Проверено на n8n 2.42.4, Aggregate версии 1.
- Только вымышленные данные. API-ключи, модель и внешняя база не нужны.
- Ручная учебная схема без отправки писем, записи в CRM и работы с реальными клиентами.
Установить n8n локально через Docker
Шаг 1. Импортируйте готовую схему
Скачать n8n-aggregate-orders.json
Создайте новый workflow. В меню редактора выберите Import from File и загрузите JSON. Если браузер открыл текст, сначала сохраните файл через «Сохранить как». На полотне должны быть пять узлов:
Manual Trigger → Sample Orders → Validate Orders → Aggregate Orders → Check Payload
Aggregate Orders — Aggregate; Sample Orders, Validate Orders и Check Payload — Code. При ручной сборке задайте эти имена и соедините узлы последовательно. Импорт не содержит credentials и чужого ID workflow, остаётся неопубликованным.
Шаг 2. Подготовьте три заказа
Откройте Sample Orders. Mode: Run Once for All Items, Language: JavaScript. Замените стандартный пример кодом ниже:
const orders = [
{
"order_id": "O1",
"client": "Анна",
"amount_minor": 150000,
"note": "Доставка утром",
"internal_note": "Учебная служебная пометка A"
},
{
"order_id": "O2",
"client": "Борис",
"amount_minor": 0,
"note": null,
"internal_note": "Учебная служебная пометка B"
},
{
"order_id": "O3",
"client": "Альфа",
"amount_minor": 49900,
"internal_note": "Учебная служебная пометка C"
}
];
if (!orders.length) throw new Error('orders_empty');
return orders.map(json => ({ json }));
| Поле | Тип | Что проверяем |
|---|---|---|
| order_id | String | Непустой уникальный ID |
| client | String | Непустое имя клиента |
| amount_minor | Number | Целые копейки от 0 |
| note | String, null или отсутствует | Разные варианты примечания |
| internal_note | String | Не включаем в результат |
Выполните триггер, затем Sample Orders либо запустите весь workflow. В Output источника должно быть три отдельных items. У O1 примечание заполнено, у O2 явно задано null, у O3 поля note нет. Служебные пометки вымышленные и нужны только для проверки отбора полей.
Шаг 3. Проверьте входные поля
В Validate Orders выберите Mode: Run Once for All Items и Language: JavaScript. Вставьте код:
const items = $input.all();
const ids = new Set();
for (const { json: row } of items) {
if (typeof row.order_id !== 'string' || !row.order_id.trim() || ids.has(row.order_id)) {
throw new Error('order_id_missing_or_duplicate');
}
if (typeof row.client !== 'string' || !row.client.trim()) throw new Error('client_required');
if (!Number.isSafeInteger(row.amount_minor) || row.amount_minor < 0) {
throw new Error('amount_minor_invalid');
}
if (row.note !== undefined && row.note !== null && typeof row.note !== 'string') {
throw new Error('note_invalid');
}
ids.add(row.order_id);
}
return items;
В Settings оставьте On Error: Stop Workflow и Execute Once выключенным. Ошибочные ID и суммы останавливают схему. Примечание может быть строкой, null или отсутствовать, но не массивом. Ноль допустим: это известная сумма, а не пропущенное значение.
Шаг 4. Выберите массив целых объектов
Откройте Aggregate Orders. В параметре Aggregate выберите All Item Data (Into a Single List). В Put Output in Field укажите orders обычным текстом. Это имя массива внутри выходного JSON.
Не выбирайте Individual Fields для основной схемы: этот режим собирает отдельные поля в отдельные списки. Нам нужны объекты заказов, чтобы ID, сумма и примечание оставались рядом.
Шаг 5. Разрешите только нужные поля
В Include выберите Specified Fields. В Fields To Include вставьте список имён:
order_id, client, amount_minor, note
Include Binaries оставьте выключенным. В Settings узла: On Error Stop Workflow, Always Output Data и Execute Once выключены. internal_note не входит в разрешённый список. Если завтра во входе появится ещё одно служебное поле, оно также не должно попасть в итоговый массив.
Это ограничение выходного документа, не очистка истории n8n. Исходные значения остаются в Sample Orders, Validate Orders и сохранённых executions. Не используйте реальные персональные данные без согласованной политики доступа и хранения.
Шаг 6. Добавьте проверку готового JSON
В Check Payload задайте Mode: Run Once for All Items, Language: JavaScript и вставьте код:
const items = $input.all();
if (items.length !== 1 || !Array.isArray(items[0].json.orders)) {
throw new Error('payload_structure_invalid');
}
const orders = items[0].json.orders;
const source = $('Validate Orders').all().map(item => item.json);
const allowed = ['order_id', 'client', 'amount_minor', 'note'];
if (orders.length !== source.length) throw new Error('payload_count_mismatch');
let total = 0;
for (let i = 0; i < orders.length; i++) {
const row = orders[i];
const expectedKeys = Object.keys(source[i]).filter(key => allowed.includes(key)).sort();
if (Object.keys(row).sort().join('|') !== expectedKeys.join('|')) {
throw new Error('payload_fields_mismatch');
}
for (const key of expectedKeys) {
if (!Object.is(row[key], source[i][key])) throw new Error('payload_value_mismatch');
}
total += row.amount_minor;
if (!Number.isSafeInteger(total)) throw new Error('payload_total_out_of_range');
}
return [{ json: {
orders,
count: orders.length,
total_amount_minor: total,
total_amount_rub: total / 100,
action_performed: false,
} }];
Код требует ровно один item с массивом orders. Для каждой позиции он сверяет набор разрешённых ключей и исходные значения. Поэтому потерянный клиент, лишнее поле, другая структура или перестановка данных не будут выданы за корректный результат.
В Settings оставьте On Error: Stop Workflow. Сумма проверяется на безопасный целочисленный диапазон JavaScript. Проверка намеренно рассчитана на один входной набор и четыре перечисленных поля простых типов; это не универсальная проверка произвольного вложенного JSON.
Шаг 7. Выполните весь workflow
Нажмите Execute Workflow. В Output Aggregate Orders должен быть 1 item, а внутри orders — 3 объекта. Один item не означает один заказ. В Check Payload ожидается:
{
"orders": [
{
"order_id": "O1",
"client": "Анна",
"amount_minor": 150000,
"note": "Доставка утром"
},
{
"order_id": "O2",
"client": "Борис",
"amount_minor": 0,
"note": null
},
{
"order_id": "O3",
"client": "Альфа",
"amount_minor": 49900
}
],
"count": 3,
"total_amount_minor": 199900,
"total_amount_rub": 1999,
"action_performed": false
}
Сверьте O1/O2/O3, русские имена, числовые суммы и примечания. internal_note в orders быть не должно. count и итоговая сумма появляются только после Check Payload. Схема ничего не отправляет, action_performed false.
Шаг 8. Проверьте ноль, null и отсутствующее поле
| Запись | Что находится в orders | Почему это важно |
|---|---|---|
| O1 | note: Доставка утром | Непустой текст сохранён |
| O2 | amount_minor: 0 и note: null | Ноль и null не потеряны |
| O3 | Ключа note нет | Отсутствие не заменено значением |
Не проверяйте сумму условием «если значение истинное»: ноль тоже корректен. Отсутствующий ключ и null могут иметь разный смысл для принимающей системы. Если ей нужны одинаковые поля во всех объектах, нормализуйте их явно до Aggregate и измените договорённую проверку. Не считайте, что узел автоматически добавит note: null у O3.
Шаг 9. Убедитесь, что проверка замечает ошибки настройки
В Put Output in Field временно замените orders на data. Запустите всю схему: Check Payload должен остановиться с payload_structure_invalid. Верните orders.
Теперь временно уберите client из Fields To Include. Ожидается payload_fields_mismatch, без успешного итогового JSON. Верните полный список из шага 5. Список, содержащий только опечатку вроде ordr_id, в проверенной версии дал пустой массив; Check Payload обнаружил payload_count_mismatch.
Для проверки лишнего поля можно на отдельной копии узла собрать All Fields: в таком результате будет internal_note, а наш Check Payload отклонит его. Не отключайте проверку ради зелёного статуса. Верните Specified Fields и разрешённый список.
Шаг 10. Сравните с отдельными списками полей
Для этого теста создайте копию workflow с названием ezGPT - Aggregate Fields Test. В копии разорвите связь Aggregate Orders → Check Payload, оставив Check Payload неподключённым: его договорённость orders относится к основной схеме, не к этому опыту.
В Aggregate Orders выберите Individual Fields. Добавьте два Fields To Aggregate. Первое: Input Field Name order_id, Rename Field on, Output Field Name ids. Второе: Input Field Name note, Rename Field on, Output Field Name notes. Keep Missing And Null Values оставьте выключенным.
Запустите копию. Результат Aggregate Orders:
{
"ids": [
"O1",
"O2",
"O3"
],
"notes": [
"Доставка утром"
]
}
ID три, а примечание только одно. При пропусках нельзя считать, что любая позиция одного списка обязательно соответствует той же позиции другого. Массив целых объектов в основном примере избавляет от такого раздельного представления записи.
Шаг 11. Сохраните пустые позиции в тестовой копии
В Options включите Keep Missing And Null Values и снова запустите тестовую копию. В сохранённом JSON результата ожидается:
{
"ids": [
"O1",
"O2",
"O3"
],
"notes": [
"Доставка утром",
null,
null
]
}
Позиции сохранены, но в списке notes уже нельзя отличить исходное null у O2 от отсутствующего поля у O3. Настройку нужно выбирать по договорённости формата, а не только по длине массива. В основной схеме используется All Item Data с массивом объектов; эта опция Individual Fields ей не требуется.
Шаг 12. Вернитесь к основной схеме и восстановите результат
Откройте ezGPT - Aggregate Orders, а не тестовую копию. Убедитесь: Aggregate All Item Data, поле orders, Specified Fields, список order_id, client, amount_minor, note; связь с Check Payload восстановлена. Исходных записей три. Снимите pin data, если закрепляли данные.
Сохраните и выполните весь workflow. Итог: один item, orders из трёх объектов, count 3, сумма 199900 копеек, служебных полей в массиве нет, action_performed false. Публикация ручной схемы не требуется.
Если в Sample Orders временно задать const orders = []; и оставить проверку длины, запуск остановится с orders_empty. Это выбранное поведение источника, не штатная ошибка Aggregate. Для допустимого пустого ответа рабочей системы отдельно спроектируйте no_data, не подставляйте фиктивный пустой заказ.
Если результат отличается
| Симптом | Причина | Что проверить |
|---|---|---|
| Один item приняли за один заказ | Количество items и объектов смешано | Длина массива orders |
| payload_structure_invalid | Имя массива или режим не совпали | All Item Data и orders |
| payload_fields_mismatch | Поле потеряно или добавлено лишнее | Specified Fields и разрешённый список |
| payload_count_mismatch | Массив потерял записи | Опечатки в полях и входной набор |
| Списки ID и примечаний разной длины | Пустые значения исключены | Individual Fields и Keep Missing |
Где заканчивается эта схема
Aggregate собирает данные, но не суммирует заказы сам по себе и не пишет текст отчёта. Здесь сумму считает наш проверочный Code. Для числовой сводки есть Summarize. Объединение разных веток workflow — другая задача, для неё нужен Merge перед дальнейшей обработкой.
Числовая сводка заказов через Summarize
Объединить данные разных потоков через Merge
Обратная операция: разделить JSON-массив через Split Out
Узел собирает только текущий вход. Если обрабатывать страницы API или пакеты отдельно, сам по себе Aggregate не гарантирует один общий массив всей выгрузки. Большие документы могут занять много памяти. Доступ, размер входа, полнота выгрузки и реальные интеграции требуют отдельных проверок.
Что проверено редакцией
15 октября 2026 года схема проверена на n8n 2.42.4 в отдельном локальном Docker-экземпляре через штатные ручные запуски API. Восемнадцать тестов: основной массив; одна запись; обратный порядок; дополнительное служебное поле; пустой источник; другое имя выходного массива; исключение обязательного поля; All Fields; строковая, null и отсутствующая сумма; дробные копейки; повтор ID; переполнение суммы; неверный тип примечания; Individual Fields без сохранения и с сохранением пропусков; список только с опечаткой поля. Сверены один выходной item, массив объектов, порядок, типы, ноль, явное null, отсутствие ключа, исключение служебных полей и итоговые счётчики. При ошибках проверенного итогового JSON нет. Individual Fields проверен отдельно без подключения Check Payload. Редакторские клики, Cloud, бинарные файлы, большие данные, пагинация, циклы и внешние API не тестировались. Настройки сверены с официальной документацией и кодом штатного Aggregate версии 1. Учебный контейнер остановлен; чужие workflows не менялись. Обложка — редакционная AI-иллюстрация.
Частые вопросы
Почему после Aggregate один item, а не три?
Узел собрал три записи внутрь массива orders одного item. Количество заказов теперь проверяется через длину массива, а не по числу items на выходе.
Aggregate считает общую сумму?
В этой схеме он собирает объекты, не считает сумму. count и total_amount_minor добавляет Check Payload. Для отдельной числовой сводки можно использовать Summarize.
Почему пропали null-примечания в Individual Fields?
При выключенном Keep Missing And Null Values такие значения пропускаются. Включение опции сохраняет пустые позиции; для хранения целых записей здесь выбран All Item Data.
Исключение internal_note удаляет его из истории n8n?
Нет. Оно ограничивает поля выходного массива. Исходные пометки могут остаться во входных узлах и сохранённых executions. Права и сроки хранения настраиваются отдельно.
Как снова получить отдельные items из orders?
Добавьте Split Out для массива orders и проверьте нужные сопутствующие поля. Это обратная операция представления данных, а не удаление или повторное создание заказов в CRM.