Выражения в n8n: Полное руководство по динамическим операциям с данными
Выражения в n8n — это мощный механизм, позволяющий динамически вычислять, форматировать и манипулировать данными непосредственно в процессе выполнения рабочего процесса (workflow). В отличие от статичных значений, выражения вычисляются в момент выполнения ноды (узла) и дают доступ к данным из предыдущих шагов, переменным окружения, датам, математическим операциям и функциям. Это ключевой инструмент для создания гибких, адаптивных и сложных автоматизаций без необходимости написания отдельного кода.
Синтаксис выражений и способы их использования
Выражения в n8n используют синтаксис, основанный на двойных фигурных скобках {{ }}. Все, что находится внутри этих скобок, интерпретируется как выражение JavaScript (с некоторыми ограничениями и расширениями) и подлежит вычислению.
Выражения можно использовать в большинстве полей ввода нод n8n. Чтобы активировать режим выражения, необходимо нажать на значок fx рядом с полем или использовать сочетание клавиш =. Поле из обычного текстового превращается в редактор выражения, где доступны автодополнение и всплывающие подсказки.
Основные компоненты выражений: Переменные и функции
Выражения строятся из двух основных компонентов: переменных, предоставляющих доступ к данным, и функций, которые эти данные обрабатывают.
Переменные выражений
Переменные дают доступ к контексту выполнения. Наиболее важные из них:
- $json: Предоставляет доступ к данным элемента (item) с предыдущей ноды. Например,
{{ $json["fieldName"] }}или{{ $json.fieldName }}. - $input: Позволяет получить данные, которые были на входе текущей ноды на первом выполнении (предотвращает зацикливание).
- $node: Дает доступ к выходным данным других нод в workflow по их имени. Например,
{{ $node["Webhook"].json["body"] }}. - $items: Содержит массив всех элементов на входе текущей ноды. Полезно для работы с индексами, например,
{{ $items[0].json.id }}. - $index: Текущий индекс элемента в выполняемой операции (начинается с 0).
- $now и $today: Объекты даты/времени для текущего момента и начала текущих суток.
- $env: Обеспечивает доступ к переменным окружения, определенным в настройках n8n. Например,
{{ $env.API_KEY }}. - $vars: Предоставляет доступ к переменным workflow, которые можно задавать через ноду «Set».
- $evaluateExpression: Позволяет динамически вычислять строку как выражение n8n.
- $jmesPath: Позволяет выполнять запросы JMESPath к JSON-данным.
- formatDate(): Форматирует дату в строку.
{{ formatDate($now, 'YYYY-MM-DD') }}. - plusTime() / minusTime(): Добавляет или вычитает интервал времени.
{{ plusTime($now, 2, 'days') }}. - extractDate(): Извлекает часть даты (день, месяц, год и т.д.).
- startOf() / endOf(): Возвращает начало или конец периода (месяца, недели).
- toLowerCase(), toUpperCase(): Изменяют регистр.
- trim(): Удаляет пробелы с обоих концов строки.
- replace(): Заменяет часть строки.
{{ replace("Hello World", "World", "n8n") }}. - split(), join(): Разделяет строку в массив и объединяет массив в строку.
- hash(): Создает хэш (md5, sha256) от строки.
- urlEncode() / urlDecode(): Кодирует/декодирует строку для URL.
- average(), sum(), min(), max(): Статистические операции над массивами чисел.
- ceil(), floor(), round(): Округление чисел.
- randomInt(): Генерация случайного целого числа в диапазоне.
- first(), last(): Получают первый или последний элемент массива.
- pluck(): Извлекает значения определенного свойства из массива объектов.
- unique(): Возвращает массив уникальных значений.
- merge(), union(): Объединяют массивы или объекты.
- isEmpty(), isNotEmpty(): Проверяют, пуст ли массив, объект или строка.
- ifEmpty(), ifNotEmpty(): Возвращают значение в зависимости от наличия данных.
- contains(), startsWith(), endsWith(): Проверяют содержание в строке.
- and(), or(), not(), xor(): Логические операторы.
- compare(): Универсальная функция для сравнения (больше, меньше, равно и т.д.).
- 1.2 } }}
- Выражения выполняются в изолированной песочнице (sandbox) и не имеют прямого доступа к файловой системе или глобальным объектам Node.js, что обеспечивает безопасность.
- При ошибке в выражении (например, обращение к несуществующему полю) нода завершится с ошибкой. Для обработки таких случаев используйте функции
ifEmpty()или??(оператор нулевого слияния). - Для отладки сложных выражений используйте ноду «Code» (JavaScript) или разбивайте выражение на части.
- Избегайте чрезмерно сложных выражений внутри циклов, обрабатывающих тысячи элементов. В таких случаях может быть эффективнее использовать ноду «Code».
- Использование
$nodeдля доступа к данным других нод требует, чтобы эти ноды были уже выполнены. Планируйте порядок выполнения workflow. - Для длинных или часто используемых выражений создавайте переменные через ноду «Set». Это повышает читаемость и упрощает повторное использование.
- Комментируйте сложные выражения, используя нотацию
{{ / Это комментарий / }}.
Категории встроенных функций
Функции в выражениях сгруппированы по категориям для удобства поиска.
Функции для работы с датами
Функции для работы со строками
Математические функции
Функции для работы с массивами и объектами
Логические функции и сравнение
Практические примеры использования выражений
Пример 1: Динамическое формирование пути файла
В ноде «Write Binary File» можно использовать выражение для имени файла:
{{ "report_" ~ formatDate($now, 'YYYY-MM-DD_HH-mm') ~ ".csv" }}
Это создаст файл с именем, например, report_2023-10-26_14-30.csv.
Пример 2: Условная логика в полях
В ноде «HTTP Request» для установки заголовка в зависимости от данных:
{{ ifNotEmpty($json.apiToken, $json.apiToken, $env.FALLBACK_TOKEN) }}
Это выражение проверит, есть ли apiToken во входящих данных. Если да — использует его, если нет — использует значение из переменной окружения.
Пример 3: Агрегация данных в массиве
Для вычисления общей суммы заказов из массива объектов:
{{ $json.orders.sum('amount') }}
Предполагается, что $json.orders — это массив, и у каждого элемента есть поле amount.
Пример 4: Создание динамического тела запроса
В ноде «HTTP Request» (метод POST) тело (body) можно задать выражением:
{{ { "id": $json.id, "processedAt": $now, "calculatedValue": $json.value
Это создаст новый JSON-объект, объединив данные из предыдущей ноды, текущее время и вычисленное значение.
Таблица: Сравнение способов доступа к данным
| Переменная | Контекст | Пример использования | Когда применять |
|---|---|---|---|
$json |
Текущий элемент | {{ $json.email }} |
Для работы с данными, пришедшими непосредственно на вход ноды. |
$node |
Любая нода в workflow | {{ $node["CSV"].json["row"][5] }} |
Когда нужны данные не из предыдущей, а из конкретной, возможно удаленной, ноды. |
$input |
Первоначальный вход ноды | {{ $input.first().json }} |
В циклах или при сложной обработке, чтобы получить доступ к исходным, а не модифицированным данным. |
$items |
Все элементы на входе | {{ $items[i].json.name }} |
Для операций, требующих знания индекса элемента или доступа ко всем элементам одновременно. |
Особенности и лучшие практики
Безопасность и ошибки
Производительность
Читаемость
Часто задаваемые вопросы (FAQ)
Вопрос: Как в выражении обратиться к данным из двух шагов назад?
Ответ: Прямого способа через $json нет. Необходимо использовать переменную $node с указанием имени конкретной ноды, данные которой вам нужны. Например: {{ $node["First Node"].json["id"] }}. Альтернативно, можно сохранить нужные данные в переменных workflow с помощью ноды «Set».
Вопрос: Можно ли использовать в выражениях стандартные методы JavaScript, например, .map() или .filter()?
Ответ: Да, но с ограничениями. Выражения выполняются в контексте движка Expression Extension, который поддерживает многие нативные методы. Например, {{ $json.array.map(item => item.value) }} часто работает. Однако для гарантированной совместимости и доступности подсказок рекомендуется использовать встроенные функции n8n, такие как pluck() или filter().
Вопрос: Чем отличается $json от $input в цикле (Loop Over Items)?
Ответ: Внутри цикла $json меняется на каждой итерации и содержит данные текущего элемента цикла. $input же всегда ссылается на тот массив данных, который поступил на вход ноды «Loop» до начала циклирования. $input.all() вернет исходный полный массив.
Вопрос: Как сделать многострочное выражение или сложную логику?
Ответ: Для сложной логики, состоящей из множества операторов, лучше использовать ноду «Code» (JavaScript или Python). Выражения предназначены для относительно коротких операций в одну строку. Однако внутри выражения можно использовать тернарный оператор condition ? valueIfTrue : valueIfFalse для базовых условий.
Вопрос: Почему выражение возвращает строку «[object Object]» вместо данных?
Ответ: Это происходит при попытке неявного преобразования объекта JavaScript в строку. Чтобы получить содержимое объекта, используйте функцию JSON.stringify() внутри выражения: {{ JSON.stringify($json.someObject) }}. Для отладки также можно использовать ноду «Code».
Вопрос: Как работать с датами и временными зонами?
Ответ: Объекты $now и $today используют временную зону сервера n8n (UTC по умолчанию). Функция formatDate() позволяет явно указать временную зону в формате строки. Например: {{ formatDate($now, 'YYYY-MM-DD HH:mm:ss', { timeZone: 'Europe/Moscow' }) }}.
Вопрос: Можно ли создавать собственные функции для выражений?
Ответ: Прямого способа добавить функцию в интерфейс выражений нет. Однако вы можете инкапсулировать повторяющуюся логику в пользовательской ноде «Function» или «Code», которая возвращает результат вычислений. Также можно использовать $evaluateExpression для динамического вызова выражений, хранящихся в виде строк.
Заключение
Выражения являются фундаментальной частью n8n, превращая его из простого инструмента для соединения API в мощную платформу для сложной обработки данных. Они обеспечивают гибкость, позволяя динамически формировать запросы, преобразовывать данные, реализовывать бизнес-логику и принимать решения прямо внутри workflow. Освоение переменных контекста, встроенных функций и лучших практик использования выражений критически важно для создания эффективных, надежных и легко поддерживаемых автоматизаций. По мере усложнения задач стоит комбинировать выражения с нодами выполнения кода, что позволяет использовать всю мощь JavaScript там, где этого требуют задачи.
Добавить комментарий