Перейти к содержимому

Что такое связь

Связь — это способ соединить две таблицы так, чтобы строка одной указывала на строку другой. Это базовый приём для аккуратного учёта: данные хранятся ровно там, где они описывают сущность, а не дублируются по всему workspace.

Что это даёт

Храните платежи отдельно от квартир — и сразу видите доход по каждой квартире.

Три житейских примера

  1. Аренда квартир.

    • «Объекты недвижимости» — список квартир. У каждой — адрес, цена, площадь.
    • «Платежи аренды» — список платежей. У каждого платежа есть связь «Объект» → квартира.
    • Хотите видеть, сколько принёс каждый объект? Группируйте платежи по этой связи.
  2. Личные финансы.

    • «Счета» — карты, депозиты, кошельки.
    • «Транзакции» — со связью «Счёт» → один из счетов.
    • Виджет KPI «остаток по карте Tinkoff» сразу даст ответ.
  3. Малый бизнес.

    • «Контрагенты» — компании и физлица.
    • «Сделки» — со связью «Контрагент» → строка из «Контрагентов».
    • Видите суммарный оборот по каждому контрагенту.

Чем отличается от тега и enum

ПризнакСвязьСписок (enum)Теги
Целевой объект — отдельная сущность?ДаНетНет
У целевого есть свои поля?Да (адрес, цена, описание)НетНет
КратностьОдна ссылка на строкуОдин из набораНесколько
Управление списком значенийЦелевой датасет (можно добавить, изменить, удалить)Опции в схеме поляРастут по мере ввода
Группировка на дашбордеДаДаЧастично

Простое правило. Если у того, на что ссылается ваше поле, есть свои собственные поля (например, у «Контрагент» есть ИНН, телефон, адрес) — это связь. Если это просто метка/категория — список или теги.

Только M:1 в MVP

В текущей версии Invest поддерживается только M:1 (multi-to-one): много строк дочернего датасета указывают на одну строку родительского.

M:1 — поддерживаетсяM:N — НЕ поддерживается
Много платежей → одна квартираНесколько собственников → одна квартира с долями
Много сделок → один контрагентНесколько тегов → много задач (используйте поле «Теги»)
Много транзакций → один счётМногие ко многим в принципе

Что это значит на пальцах. Если вы говорите «у меня много A и одна B на каждое A» — это работает (связь добавляется в датасет A, указывает на B). Если же «у каждой A может быть несколько B и у каждой B — несколько A» — это M:N, и пока не работает. Workaround: либо моделируйте через таблицу-связку (датасет «AB» с двумя связями M:1), либо ждите будущих версий.

Пошаговое создание

Возьмём пример «Объекты ↔ Платежи аренды».

  1. Создайте родительский датасет «Объекты недвижимости». Подробно — в «Первая таблица». Добавьте поля: address, purchase_price, monthly_rent и т. д.

  2. Создайте дочерний датасет «Платежи аренды». Поля: payment_date (Дата), amount (Деньги).

  3. В схеме «Платежей» добавьте поле:

    Поле «Связь» в форме создания

    • Название: «Объект»
    • Ключ: object
    • Тип: «Связь»
    • Целевой датасет: «Объекты недвижимости»
  4. Сохраните.

  5. Перейдите в таблицу «Платежей», добавьте строку. В колонке «Объект» появится выпадающий список — выберите квартиру.

  6. Возвращайтесь в «Объекты» — там вы по-прежнему один объект, но через виджет вы сможете отображать сумму платежей по каждому.

Альтернатива: подробный гайд с акцентом на UI — в «Как создать связь».

Поведение при удалении родителя

⚠️ Уточнить: конкретное правило (SET NULL или CASCADE) на уровне хранилища для связи M:1 в jsonb в текущей версии не отражено явно в коде. Перед массовой операцией удаления родительских строк, у которых есть дочерние, проверьте поведение на тестовых данных или спросите поддержку.

Что точно: «потерянные» дочерние строки не пропадают физически в течение 30 дней (мягкое удаление), даже если родитель удалён.

В формулах

В формуле поле-связь хранит только id целевой строки, не её поля. Точечной нотации (object.price) в формулах нет. Подробный разбор и обходные пути — в «Связи в формулах».

В виджетах

  • Таблица: связь рендерится как имя целевой строки + ссылка-переход.
  • Графики/Donut/Top-N: можно группировать по связи, чтобы получить «по квартирам».
  • Глобальный фильтр: фильтрует все виджеты, использующие данный ключ-связи.
  • Drill-down: клик по сегменту покажет дочерние строки этой связи.

Ограничения MVP

  • Только M:1.
  • Связь нельзя сделать обязательной с уровня UI (required для связи) — поле всё равно может быть пустым. > ⚠️ Уточнить: проверьте текущее поведение required для типа relation перед массовой загрузкой.
  • Нет автоматических проверок «нельзя оставить связь пустой при создании дочерней строки».
  • Связи на самого себя (self-relation) работают.

Частые ошибки

  • Забыли выбрать запись в связи. Дочерняя строка создаётся с пустой связью. В виджетах она попадёт в группу «без значения» или будет пропущена.
  • Удалили родителя, а дочерние остались на старом id. Если поведение каскада SET NULL — связь теряется. Если CASCADE — пропадают и дочерние.
  • Выбрали не тот целевой датасет. Поправить тип-целевой датасет существующей связи будет сложнее, чем создать новое поле и перенести значения.
  • Хотят M:N через связь. Не работает напрямую. См. workaround выше.

Что дальше