Список заказов может приходить в случайном порядке. Если сначала нужно увидеть самые крупные, используйте Sort в n8n. В этой инструкции отсортируем четыре заказа по сумме, а при равных суммах — по отдельному числовому ключу. Проверим, что записи не исчезли и порядок воспроизводится.
Результат инструкции
Workflow ezGPT - Sort Orders получает O3, O1, O4, O2. После сортировки по amount_minor от большего к меньшему и по order_rank от меньшего к большему выдаёт O1, O3, O2, O4. Суммы: 150000, 150000, 90000 и 0 копеек. Общая сумма остаётся 390000 копеек, или 3900 рублей.
Sort меняет порядок items, не отбирает и не оплачивает заказы. В конце будет сводка с ID и суммами в новом порядке, count 4 и action_performed false. AI здесь не нужен: используем обычную сортировку и явные проверки данных.
Что понадобится
- Работающий n8n и права создать отдельный workflow. Пример проверен на n8n 2.42.4, узел Sort версии 1.
- Только вымышленные заказы. API-ключи и внешние сервисы не нужны.
- Учебная схема с ручным запуском, без подключения CRM, оплаты и рассылки.
Установить локальный n8n через Docker
Шаг 1. Импортируйте готовую схему
Создайте новый workflow. В меню редактора выберите Import from File и загрузите JSON. Если браузер показывает текст, сохраните файл через «Сохранить как», затем импортируйте его. На полотне должны быть пять узлов:
Manual Trigger → Sample Orders → Validate Orders → Sort Orders → Sort Summary
Sample Orders, Validate Orders и Sort Summary — Code. Sort Orders — Sort. При ручной сборке добавьте эти узлы и соедините в указанном порядке. Импорт не содержит credentials и чужого ID workflow, остаётся неопубликованным.
Шаг 2. Подготовьте исходные заказы
Откройте Sample Orders. Mode: Run Once for All Items, Language: JavaScript. Вставьте полный код:
const orders = [
{
"order_id": "O3",
"order_rank": 3,
"client": "Гамма",
"amount_minor": 150000
},
{
"order_id": "O1",
"order_rank": 1,
"client": "Альфа",
"amount_minor": 150000
},
{
"order_id": "O4",
"order_rank": 4,
"client": "Дельта",
"amount_minor": 0
},
{
"order_id": "O2",
"order_rank": 2,
"client": "Бета",
"amount_minor": 90000
}
];
if (!orders.length) throw new Error('orders_empty');
return orders.map(json => ({ json }));
| Поле | Тип | Правило примера |
|---|---|---|
| order_id | String | Непустой уникальный ID |
| order_rank | Number | Уникальное целое число от 1 |
| client | String | Непустое имя клиента |
| amount_minor | Number | Целые копейки, не меньше 0 |
order_rank — специально заданный ключ для одинаковых сумм, не номер строки после сортировки и не оценка клиента. У O1 значение 1, у O3 — 3: при одинаковой сумме O1 должен идти раньше. Если в рабочей системе такого ключа нет, сначала выберите другой однозначный критерий, например время создания и уникальный ID.
Нажмите Execute Workflow либо выполните триггер, затем Sample Orders. Его Output должен содержать четыре отдельных items в порядке O3, O1, O4, O2. Это не один item с массивом orders внутри.
Шаг 3. Проверьте типы до сортировки
Откройте Validate Orders. Mode: Run Once for All Items, Language: JavaScript. Вставьте код ниже. В Settings оставьте On Error: Stop Workflow и Execute Once выключенным.
const items = $input.all();
const ids = new Set();
const ranks = 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 (!Number.isSafeInteger(row.order_rank) || row.order_rank < 1 || ranks.has(row.order_rank)) {
throw new Error('order_rank_invalid_or_duplicate');
}
if (!Number.isSafeInteger(row.amount_minor) || row.amount_minor < 0) {
throw new Error('amount_minor_invalid');
}
if (typeof row.client !== 'string' || !row.client.trim()) {
throw new Error('client_required');
}
ids.add(row.order_id);
ranks.add(row.order_rank);
}
return items;
Код возвращает те же items без изменения значений. Он запрещает пустые и повторные ID, повторный или неверный order_rank, строковые и дробные копейки. Ноль допустим. Эти правила относятся к нашему учебному набору: если реальные записи отличаются, согласуйте схему и преобразование до Sort.
Число 150000 и строка «150000» — разные значения. Не рассчитывайте, что сортировка сама очистит пробелы, исправит валюту и восстановит отсутствующую сумму. Пустая сумма не должна превращаться в нулевую только ради успешного запуска.
Шаг 4. Настройте сортировку суммы
Откройте Sort Orders. Type: Simple. В Fields To Sort By добавьте первое поле через Add Field To Sort By: Field Name — amount_minor, Order — Descending.
Field Name вводится обычным текстом в Fixed: amount_minor. Здесь не нужно вставлять выражение {{ $json.amount_minor }} или конкретную сумму из одного заказа. Descending означает, что большие значения будут раньше маленьких.
Шаг 5. Добавьте второй ключ
Нажмите Add Field To Sort By ещё раз. Во второй строке Field Name: order_rank, Order: Ascending. Первой должна оставаться amount_minor. Настройки в готовом workflow выглядят так:
1. amount_minor — Descending
2. order_rank — Ascending
Первое поле задаёт основной порядок. Второе сравнивается, когда суммы равны. Если поставить order_rank первым, получится порядок O1, O2, O3, O4, а не список от крупных заказов к мелким.
В Options оставьте Disable Dot Notation выключенным; в нашем наборе поля находятся на верхнем уровне. Для вложенного поля вроде totals.amount_minor точечная запись означает путь внутрь объекта. Здесь никаких вложенных полей не требуется.
Шаг 6. Добавьте сводку после Sort
Откройте Sort Summary. Mode: Run Once for All Items, Language: JavaScript. Вставьте код:
const rows = $input.all().map(item => item.json);
let total = 0;
for (const row of rows) {
total += row.amount_minor;
if (!Number.isSafeInteger(total)) throw new Error('total_out_of_range');
}
return [{ json: {
count: rows.length,
sorted_ids: rows.map(row => row.order_id),
amounts_minor: rows.map(row => row.amount_minor),
total_amount_minor: total,
total_amount_rub: total / 100,
action_performed: false,
} }];
sorted_ids и amounts_minor идут в одном порядке: первый ID соответствует первой сумме. total_amount_minor проверяется на безопасный целочисленный диапазон. Сводка не отправляет заказы во внешние системы.
У Sort Orders и Sort Summary оставьте Always Output Data выключенным и On Error: Stop Workflow. Наш пример не использует пустой объект как заказ; отсутствие исходных заказов обрабатывается раньше, в Sample Orders.
Шаг 7. Запустите всю цепочку и сравните результат
Нажмите Execute Workflow. В Output узла Sort Orders должны остаться все четыре заказа, но в новом порядке:
| Позиция / ID | Сумма в копейках | Почему здесь |
|---|---|---|
| 1 / O1 | 150000 | Равная максимальная сумма, rank 1 |
| 2 / O3 | 150000 | Та же сумма, rank 3 |
| 3 / O2 | 90000 | Меньше 150000, больше 0 |
| 4 / O4 | 0 | Самая маленькая сумма |
В Sort Summary ожидается:
{
"count": 4,
"sorted_ids": [
"O1",
"O3",
"O2",
"O4"
],
"amounts_minor": [
150000,
150000,
90000,
0
],
"total_amount_minor": 390000,
"total_amount_rub": 3900,
"action_performed": false
}
Сверьте client, order_id, order_rank и amount_minor с источником. Сортировка не должна переписывать значения. Если записей стало меньше, ищите фильтр или другую обработку до Sort; сам наш Sort ничего не исключает.
Шаг 8. Проверьте равные суммы при другом входном порядке
В Sample Orders поменяйте местами объекты O3 и O1, не меняя их поля. Запустите весь workflow: O1 всё равно должен идти перед O3. Затем восстановите исходный список.
Чтобы увидеть роль второго ключа, временно удалите order_rank из Fields To Sort By, оставив amount_minor Descending. На исходном наборе в проверенной версии порядок равных сумм будет O3, O1; после перестановки исходных объектов — O1, O3. Это сохранение входного порядка равных значений, а не сортировка по ID.
Верните order_rank Ascending второй строкой. Теперь порядок равных сумм задаётся данными, а не случайной последовательностью ответа API. Не меняйте Type на Random: он предназначен для перемешивания, а не очереди по сумме.
Шаг 9. Сравните Ascending и Descending
У первого поля amount_minor временно поменяйте Order на Ascending. Второе поле order_rank оставьте Ascending. После запуска ожидается O4, O2, O1, O3: сначала 0, затем 90000, затем два заказа по 150000. Количество и общая сумма остаются прежними.
Верните amount_minor Descending. Для дополнительной проверки временно поставьте order_rank Descending: среди равных сумм первым станет O3, затем O1. После теста верните order_rank Ascending. Изменяйте только одну настройку за раз, иначе будет трудно понять причину нового порядка.
Шаг 10. Проверьте неверные значения и дубли
В Sample Orders у O3 временно замените число 150000 на строку «150000», заключив его в кавычки. Запустите всю схему: Validate Orders должен остановиться с amount_minor_invalid; успешной сводки не будет. Верните число без кавычек.
Аналогично проверьте amount_minor: null, число 150000.5 или -1. Каждый из этих вариантов нарушает правила копеек нашего примера. Верните 150000. Удаление amount_minor тоже не должно дать корректный результат.
Теперь временно задайте O1 order_rank 3, как у O3: ожидается order_rank_invalid_or_duplicate. Повторный order_id должен вызвать order_id_missing_or_duplicate. Восстановите rank 1 и ID O1. Эти проверки добавлены нашим Code; Sort сам не является узлом поиска дублей.
Шаг 11. Проверьте отсутствие исходных заказов
В Sample Orders временно замените массив на пустой: const orders = []; Остальные строки с проверкой длины и return оставьте. Запустите цепочку: источник должен остановиться с orders_empty, а Sort и сводка не должны успешно выполниться.
Это выбранное поведение учебного примера. В реальном отчёте отсутствие заказов может быть нормальным результатом; тогда заранее добавьте отдельную ветку no_data до разворачивания массива. Не создавайте фиктивный заказ с нулевой суммой и не маскируйте ошибку загрузки как пустую выгрузку.
Восстановите четыре объекта. Если в Sort опечататься в Field Name, например amunt_minor, ожидается ошибка поиска поля. Пустой список Fields To Sort By тоже является ошибкой. Верните два правильных поля.
Шаг 12. Восстановите схему и зафиксируйте итог
Проверьте исходные четыре заказа. В Sort: Type Simple, первое поле amount_minor Descending, второе order_rank Ascending. Все три Code-узла работают в Run Once for All Items, ошибки останавливают workflow. Снимите pin data, если закрепляли данные во время отладки.
Сохраните изменения и выполните весь workflow заново. Итог: O1, O3, O2, O4; четыре записи; сумма 390000 копеек; исходные поля сохранены; action_performed false. Схема остаётся ручной, для этого результата публикация не требуется.
Перед сортировкой оставить только нужные записи через Filter
Получить все страницы API до обработки
Если результат отличается
| Симптом | Причина | Что проверить |
|---|---|---|
| Мелкие заказы впереди | Сумма сортируется по возрастанию | amount_minor: Descending |
| Равные суммы меняются местами | Нет второго однозначного ключа | order_rank: Ascending |
| Порядок строго O1, O2, O3, O4 | Ранг стал главным полем | Поставьте сумму первой |
| amount_minor_invalid | Строка, null или неверное число | JSON Number, целые копейки от 0 |
| Ошибка поиска поля | Опечатка или неверный путь | Field Name как текст, без выражения |
Перед сортировкой реальных данных
Sort упорядочивает набор, который получил в текущем запуске. Если API отдаёт страницы или данные идут пакетами в цикле, сортировка каждого пакета не создаёт общий порядок всего списка. Сначала получите полный нужный набор либо используйте сортировку на стороне источника с согласованной пагинацией.
Сортировка массива внутри одного item — отдельная задача. Эта схема работает с несколькими items. Для JSON с массивом orders сначала нужны проверка источника и Split Out; нельзя вписать orders.amount_minor и считать, что вложенный массив автоматически развернулся.
Разделить JSON-массив на отдельные items
Первые заказы в списке не получают разрешение на оплату или особые права. Если дальше добавляете действия, отдельно нужны проверка доступа, защита от повторов и подтверждение. В этом примере нет внешних записей; сортировка не изменяет порядок строк в CRM или исходной таблице.
Что проверено редакцией
14 октября 2026 года схема проверена на n8n 2.42.4 в отдельном локальном Docker-экземпляре через штатные ручные запуски API. Двадцать два теста: основной порядок; обратный входной список; сумма Ascending; второй ключ Descending; ранг первым; один ключ на исходном и обратном списке; числовые значения 2, 10, 100 и 0; все суммы равны; одна запись; пустой набор; строковая, отсутствующая и null-сумма; дробные и отрицательные копейки; повтор ID; повтор и строковый ранг; переполнение общей суммы; неверное имя поля; отсутствие полей сортировки. Сверены точный порядок, количество, все значения записей, счётчики, суммы и action_performed false. При ошибках успешной сводки нет. Редакторские клики, Cloud, большие наборы, пагинация и циклы в этой схеме не тестировались. Официальные настройки сверены с документацией и кодом штатного Sort версии 1. Учебный контейнер остановлен; чужие workflows не менялись. Обложка — редакционная AI-иллюстрация.
Частые вопросы
Почему крупные суммы оказались внизу?
Проверьте первое поле amount_minor и его Order. Для крупных сумм сверху нужен Descending. Ascending ставит маленькие значения раньше больших.
Зачем второй ключ, если сортировка уже работает?
Он задаёт порядок при равных суммах. Без него в проверенной версии сохраняется входной порядок равных записей; он может меняться между выгрузками. Здесь используется уникальный числовой order_rank.
Можно ли сортировать суммы, пришедшие строкой?
Сначала явно преобразуйте и проверьте их по правилам источника. Наша схема намеренно отклоняет строки до Sort, не меняет пустую сумму на ноль и использует только целые числовые копейки.
Sort удаляет записи или меняет поля?
В этом примере Sort меняет только порядок всех четырёх items. ID, клиент, ранг и сумма сохранены. Для отбора записей нужен отдельный Filter, а для записи в CRM — отдельная интеграция.
Как отсортировать массив внутри одного JSON?
Сначала разверните массив в отдельные items через Split Out и проверьте поля. Этот workflow рассчитан на отдельные записи, а не на один item с вложенным списком заказов.