Условия и ветвление
Полный справочник операторов и семантика ветвления узла Условие — каждый оператор, правила истинности/ложности и как распространяются пропущенные ветви.
Условия и ветвление
Узел Условие — это двусторонний маршрутизатор: он вычисляет группу условий по данным выше по потоку и направляет выполнение либо по ветви true, либо по ветви false. system-nodes.mdx кратко описывает входы, выходы и форму config; эта страница — глубокий справочник по полному каталогу операторов, правилам приведения, которые применяет исполнитель, тому, как распространяются пропущенные ветви, и тому, как выразить составную логику, когда одного узла недостаточно.
Семантика ветвления
Обработчик Условия в движке вычисляет ConditionConfig узла по разрешённому контексту выше по потоку и пишет событие step_completed с outputData: { branch: "true" | "false" }. Затем он проходит по каждой исходящей связи из узла — каждая связь несёт sourceHandle, равный либо "true", либо "false" — и делает две вещи для ветви, которая не была взята:
- Добавляет id каждой непринятой связи в множество
skippedEdgeIdsисполнителя, чтобы DAG-резолвер считал эти связи удовлетворёнными, а не ожидающими. Это позволяетcascadeSkipпродолжать движение дальше по потоку за узлом Условие. - Вызывает
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_CONTAINS | string, string | first.includes(second) | "acme corp" содержит "corp" → true |
TEXT_DOES_NOT_CONTAIN | string, string | !first.includes(second) | "acme corp" не содержит "gmbh" → true |
TEXT_EXACTLY_MATCHES | string, string | first === second | "paid" точно равно "paid" → true |
TEXT_DOES_NOT_EXACTLY_MATCH | string, string | first !== second | "paid" не равно точно "PAID" → true |
TEXT_STARTS_WITH | string, string | first.startsWith(second) | "+79851234567" начинается с "+7" → true |
TEXT_DOES_NOT_START_WITH | string, string | !first.startsWith(second) | "user@acme.com" не начинается с "admin@" → true |
TEXT_ENDS_WITH | string, string | first.endsWith(second) | "order.pdf" заканчивается на ".pdf" → true |
TEXT_DOES_NOT_END_WITH | string, 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_TO | number|numeric-string | a === b после приведения | "100" равно 100 → true |
NUMBER_NOT_EQUAL_TO | number|numeric-string | a !== b после приведения | 99 не равно 100 → true |
NUMBER_GREATER_THAN | number|numeric-string | a > b после приведения | 150 больше "100" → true |
NUMBER_LESS_THAN | number|numeric-string | a < b после приведения | 50 меньше 100 → true |
NUMBER_GREATER_THAN_OR_EQUAL_TO | number|numeric-string | a >= b после приведения | 100 больше или равно 100 → true |
NUMBER_LESS_THAN_OR_EQUAL_TO | number|numeric-string | a <= 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_TRUE | any | toBooleanValue(first) === true | true или "true" → true; 1 → false |
BOOLEAN_IS_FALSE | any | toBooleanValue(first) === false | любое значение, кроме true / "true" → true |
Existence (2)
Операторы существования проверяют, произвёл ли разрешённый путь field хоть какое-то значение. Они используют строгие проверки на null/undefined, так что пустая строка "", число 0, false и пустые массивы все считаются существующими.
| Оператор | Типы операндов | Семантика | Пример |
|---|---|---|---|
EXISTS | any | first !== null && first !== undefined | "" существует → true; отсутствующее поле → false |
DOES_NOT_EXIST | any | first === null || first === undefined | отсутствующее поле company → true |
List (4)
Операторы списков требуют, чтобы левый операнд был массивом JavaScript. Если нет — включая случай, когда поле отсутствует или является объектом — они возвращают false. LIST_CONTAINS / LIST_DOES_NOT_CONTAIN используют Array.prototype.includes, основанный на строгом равенстве и не заглядывающий внутрь членов объектов; для более глубокого сопоставления используйте FILTER или LOOP.
| Оператор | Типы операндов | Семантика | Пример |
|---|---|---|---|
LIST_CONTAINS | array, any | first.includes(second) (строгое равенство) | ["paid", "trial"] содержит "paid" → true |
LIST_DOES_NOT_CONTAIN | array, any | !first.includes(second) | ["paid", "trial"] не содержит "free" → true |
LIST_IS_EMPTY | array | first.length === 0 | [] пуст → true |
LIST_IS_NOT_EMPTY | array | first.length > 0 | ["a"] не пуст → true |
Date (1)
Оператор дат приводит каждую сторону через toDate(): строки и числа передаются в new Date(), всё остальное становится null. Невалидные даты (new Date(...) возвращает время NaN) также становятся null. Если какая-то сторона null, оператор возвращает false. Сравнения — в миллисекундах с эпохи, так что ISO-строка и Unix-таймстемп корректно сравниваются друг с другом.
| Оператор | Типы операндов | Семантика | Пример |
|---|---|---|---|
DATE_IS_BEFORE | string|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}}разрешаются по выходам выше по потоку. - Обработка ошибок — что произойдёт на живой ветви, если нижестоящее действие упадёт.