Документация Triggo
Конструктор workflow

Условия и ветвление

Полный справочник операторов и семантика ветвления узла Условие — каждый оператор, правила истинности/ложности и как распространяются пропущенные ветви.

Условия и ветвление

Узел Условие — это двусторонний маршрутизатор: он вычисляет группу условий по данным выше по потоку и направляет выполнение либо по ветви true, либо по ветви false. system-nodes.mdx кратко описывает входы, выходы и форму config; эта страница — глубокий справочник по полному каталогу операторов, правилам приведения, которые применяет исполнитель, тому, как распространяются пропущенные ветви, и тому, как выразить составную логику, когда одного узла недостаточно.

Семантика ветвления

Обработчик Условия в движке вычисляет ConditionConfig узла по разрешённому контексту выше по потоку и пишет событие step_completed с outputData: { branch: "true" | "false" }. Затем он проходит по каждой исходящей связи из узла — каждая связь несёт sourceHandle, равный либо "true", либо "false" — и делает две вещи для ветви, которая не была взята:

  1. Добавляет id каждой непринятой связи в множество skippedEdgeIds исполнителя, чтобы DAG-резолвер считал эти связи удовлетворёнными, а не ожидающими. Это позволяет cascadeSkip продолжать движение дальше по потоку за узлом Условие.
  2. Вызывает getBranchNodes(definition, node.id, skippedBranch), чтобы перечислить каждого потомка, достижимого только через отсечённую ветвь, и дописывает событие журнала step_skipped для каждого. Эти узлы добавляются в completedNodeIds без единого выполнения.

Выход самого узла Условие — { branch: "true" | "false", matched: <boolean[] по каждому условию> }. matched — индивидуальный результат каждого под-условия до применения комбинатора AND/OR — полезно при отладке, чтобы понять, какая строка в группе из нескольких условий сработала.

Входы для нижестоящего Объединения

Когда ветвь пропущена, а ниже по потоку стоит узел Объединение, Объединение не ждёт вечно отсечённый вход. Обработчик Объединения трактует связь, чья ветвь была пропущена, как отдающую null для этого targetHandle, так что join завершается, как только придут живые ветви. См. и раздел Объединение в system-nodes.mdx.

Справочник операторов

Каждая строка ниже — оператор, объявленный в. В примерах значение field — слева от сравнения (разрешается из контекста выше по потоку по имени поля в вашей строке условия), а сконфигурированное value — справа. Всего 23 оператора.

Text (8)

Все текстовые операторы требуют, чтобы оба операнда были строками JavaScript. Если одна из сторон отсутствует или не строка, оператор возвращает false без приведения — числа не превращаются в строки, null/undefined не совпадают с пустой строкой. Все текстовые сравнения регистрозависимы.

ОператорТипы операндовСемантикаПример
TEXT_CONTAINSstring, stringfirst.includes(second)"acme corp" содержит "corp" → true
TEXT_DOES_NOT_CONTAINstring, string!first.includes(second)"acme corp" не содержит "gmbh" → true
TEXT_EXACTLY_MATCHESstring, stringfirst === second"paid" точно равно "paid" → true
TEXT_DOES_NOT_EXACTLY_MATCHstring, stringfirst !== second"paid" не равно точно "PAID" → true
TEXT_STARTS_WITHstring, stringfirst.startsWith(second)"+79851234567" начинается с "+7" → true
TEXT_DOES_NOT_START_WITHstring, string!first.startsWith(second)"user@acme.com" не начинается с "admin@" → true
TEXT_ENDS_WITHstring, stringfirst.endsWith(second)"order.pdf" заканчивается на ".pdf" → true
TEXT_DOES_NOT_END_WITHstring, string!first.endsWith(second)"invoice.pdf" не заканчивается на ".docx" → true

Number (6)

Числовые операторы приводят обе стороны через toNumber(): настоящее число JavaScript проходит как есть (кроме NaN, который становится null), числовая строка парсится через Number(value), всё остальное становится null. Если какая-либо сторона приводится к null, оператор возвращает false. Это значит, что "42" равно 42, но true, null, undefined, массивы и объекты не проходят сравнение.

ОператорТипы операндовСемантикаПример
NUMBER_EQUAL_TOnumber|numeric-stringa === b после приведения"100" равно 100 → true
NUMBER_NOT_EQUAL_TOnumber|numeric-stringa !== b после приведения99 не равно 100 → true
NUMBER_GREATER_THANnumber|numeric-stringa > b после приведения150 больше "100" → true
NUMBER_LESS_THANnumber|numeric-stringa < b после приведения50 меньше 100 → true
NUMBER_GREATER_THAN_OR_EQUAL_TOnumber|numeric-stringa >= b после приведения100 больше или равно 100 → true
NUMBER_LESS_THAN_OR_EQUAL_TOnumber|numeric-stringa <= b после приведения100 меньше или равно 100 → true

Boolean (2)

Булевы операторы приводят только левый операнд и игнорируют правый. Приведение намеренно узкое: литерал true и строка "true" читаются как true; всё остальное — включая false, "false", "True", 1, 0, null, undefined, массивы и объекты — читается как false. Если нужно ветвиться по "yes", "1" или JSON true внутри строки, используйте TEXT_EXACTLY_MATCHES.

ОператорТипы операндовСемантикаПример
BOOLEAN_IS_TRUEanytoBooleanValue(first) === truetrue или "true" → true; 1 → false
BOOLEAN_IS_FALSEanytoBooleanValue(first) === falseлюбое значение, кроме true / "true" → true

Existence (2)

Операторы существования проверяют, произвёл ли разрешённый путь field хоть какое-то значение. Они используют строгие проверки на null/undefined, так что пустая строка "", число 0, false и пустые массивы все считаются существующими.

ОператорТипы операндовСемантикаПример
EXISTSanyfirst !== null && first !== undefined"" существует → true; отсутствующее поле → false
DOES_NOT_EXISTanyfirst === null || first === undefinedотсутствующее поле company → true

List (4)

Операторы списков требуют, чтобы левый операнд был массивом JavaScript. Если нет — включая случай, когда поле отсутствует или является объектом — они возвращают false. LIST_CONTAINS / LIST_DOES_NOT_CONTAIN используют Array.prototype.includes, основанный на строгом равенстве и не заглядывающий внутрь членов объектов; для более глубокого сопоставления используйте FILTER или LOOP.

ОператорТипы операндовСемантикаПример
LIST_CONTAINSarray, anyfirst.includes(second) (строгое равенство)["paid", "trial"] содержит "paid" → true
LIST_DOES_NOT_CONTAINarray, any!first.includes(second)["paid", "trial"] не содержит "free" → true
LIST_IS_EMPTYarrayfirst.length === 0[] пуст → true
LIST_IS_NOT_EMPTYarrayfirst.length > 0["a"] не пуст → true

Date (1)

Оператор дат приводит каждую сторону через toDate(): строки и числа передаются в new Date(), всё остальное становится null. Невалидные даты (new Date(...) возвращает время NaN) также становятся null. Если какая-то сторона null, оператор возвращает false. Сравнения — в миллисекундах с эпохи, так что ISO-строка и Unix-таймстемп корректно сравниваются друг с другом.

ОператорТипы операндовСемантикаПример
DATE_IS_BEFOREstring|number (парсится как Date), то жеa.getTime() < b.getTime()"2026-04-01" раньше "2026-05-01" → true

Правила истинности, ложности и приведения

Краткое резюме правил, выведенных из condition-operators:

  • Строки против чисел. Только числовые операторы приводят. Каждый текстовый оператор проверяет, что обе стороны — string, и возвращает false иначе. Никогда не полагайтесь на TEXT_EXACTLY_MATCHES против числа — приведите его к строке выше по потоку через узел Установить значения, если нужно.
  • null и undefined. Все операторы, кроме EXISTS, DOES_NOT_EXIST и булевых операторов, возвращают false, когда любая релевантная сторона — null или undefined. EXISTS возвращает true для пустых строк, 0, false и [] — всё это определённые значения.
  • Булевы. Булевы операторы принимают как истинное только литерал true или точную строку "true". Это сделано намеренно, чтобы полезные нагрузки вебхуков, которые варьируются между true, "true", "yes" и 1, были предсказуемы.
  • Массивы. Операторы списков требуют настоящий массив; объект с числовыми ключами — не массив. LIST_CONTAINS использует строгое равенство, так что [1, 2, 3] не содержит "1".
  • Даты. Любое значение, которое new Date() парсит в не-NaN время, валидно. ISO 8601 строки и миллисекунды Unix-эпохи оба работают; произвольные форматированные строки (например, "4/1/2026") зависят от парсера, и их лучше избегать.
  • Чувствительность к регистру. Текстовые операторы всегда регистрозависимы. Схема ConditionConfig принимает опциональный флаг caseSensitive для совместимости наперёд, но вычислитель операторов сегодня его не читает. Приведите обе стороны к нижнему регистру через узел Установить значения, если нужно сопоставление без учёта регистра.

Комбинирование условий

Один узел Условие уже нативно поддерживает составную логику. ConditionConfig несёт массив строк-условий плюс combinator "AND" или "OR":

  • combinator: "AND" → ветвь берётся, только когда каждая строка вычисляется в true (per.every(Boolean)).
  • combinator: "OR" → ветвь берётся, когда любая строка вычисляется в true (per.some(Boolean)).

Это покрывает большинство двусторонних ветвлений. Когда нужно больше двух направлений или смесь AND и OR, которую один комбинатор не выразит, продукт поддерживает два паттерна:

  • Цепочка узлов Условие для AND-of-OR. Поставьте одно Условие после другого на ветви true. Каждый узел дополнительно сужает выборку; любой false по цепочке отсекает остальное через обычный механизм пропущенных связей.
  • Переключатель для N-сторонней маршрутизации. Когда у вас три или более взаимоисключающих направлений — страна, тариф, имя события — тянитесь за узлом Переключатель. Переключатель вычисляет свои ветви по порядку и берёт первое совпадение, с опциональным handle fallback. См. раздел Переключатель в system-nodes.mdx.
  • Параллельные узлы Условие для OR-of-AND. Если два независимых составных предиката должны запускать одно и то же действие, разветвите узел выше по потоку на два узла Условие и соедините их ветви true на Объединении перед общим нижестоящим шагом.

Вложенная булева логика за пределами этих паттернов — знак, что ветвление стоит перенести в узел Код, возвращающий простой флаг, по которому уже ветвится одно Условие.

Пример — обогащение лида через вебхук

Реалистичный игрушечный сценарий, использующий операторы существования от начала до конца:

Webhook · lead_captured                   -- body: { email, name }
  → HTTP Request · GET /enrichment/:email  -- output: { company?: string }
  → Условие (combinator: AND,
               conditions: [
                 { field: "company", operator: EXISTS }
               ])

       ├── true  → HubSpot · Upsert contact (with company)
       │        → Slack · "New enriched lead: {{trigger.name}} at {{company}}"

       └── false → HubSpot · Upsert contact (basic)
                 → Slack · "New lead (no enrichment): {{trigger.name}}"

Строка EXISTS — ключевая ячейка в таблице Existence: она возвращает true для любого значения, которое не null и не undefined, — ровно семантика «вызов обогащения вернул название компании, даже если пустую строку». Если хотите трактовать "" тоже как отсутствующее, замените EXISTS на TEXT_DOES_NOT_EXACTLY_MATCH со значением "", скомбинировав с EXISTS под combinator: "AND".

Смотрите также

  • Системные узлы — входы, выходы и однострочная семантика для Условия, Переключателя, Объединения, Цикла и остального семейства потока.
  • Сопоставление полей — как пути field вида trigger.body.email и {{nodeId.company}} разрешаются по выходам выше по потоку.
  • Обработка ошибок — что произойдёт на живой ветви, если нижестоящее действие упадёт.

On this page