Выражения в n8n

Выражения в 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: Динамическое формирование пути файла

    В ноде «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

  • 1.2 } }}

  • Это создаст новый JSON-объект, объединив данные из предыдущей ноды, текущее время и вычисленное значение.

    Таблица: Сравнение способов доступа к данным

    Переменная Контекст Пример использования Когда применять
    $json Текущий элемент {{ $json.email }} Для работы с данными, пришедшими непосредственно на вход ноды.
    $node Любая нода в workflow {{ $node["CSV"].json["row"][5] }} Когда нужны данные не из предыдущей, а из конкретной, возможно удаленной, ноды.
    $input Первоначальный вход ноды {{ $input.first().json }} В циклах или при сложной обработке, чтобы получить доступ к исходным, а не модифицированным данным.
    $items Все элементы на входе {{ $items[i].json.name }} Для операций, требующих знания индекса элемента или доступа ко всем элементам одновременно.

    Особенности и лучшие практики

    Безопасность и ошибки

    • Выражения выполняются в изолированной песочнице (sandbox) и не имеют прямого доступа к файловой системе или глобальным объектам Node.js, что обеспечивает безопасность.
    • При ошибке в выражении (например, обращение к несуществующему полю) нода завершится с ошибкой. Для обработки таких случаев используйте функции ifEmpty() или ?? (оператор нулевого слияния).
    • Для отладки сложных выражений используйте ноду «Code» (JavaScript) или разбивайте выражение на части.

    Производительность

    • Избегайте чрезмерно сложных выражений внутри циклов, обрабатывающих тысячи элементов. В таких случаях может быть эффективнее использовать ноду «Code».
    • Использование $node для доступа к данным других нод требует, чтобы эти ноды были уже выполнены. Планируйте порядок выполнения workflow.

    Читаемость

    • Для длинных или часто используемых выражений создавайте переменные через ноду «Set». Это повышает читаемость и упрощает повторное использование.
    • Комментируйте сложные выражения, используя нотацию {{ / Это комментарий / }}.

Часто задаваемые вопросы (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 там, где этого требуют задачи.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *