Как реализовать иерархическую структуру (дерево) в 1С 8.3 с сохранением в базе данных?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке конфигураций на платформе 1С 8.3 программисты часто сталкиваются с необходимостью отображения данных в виде иерархии. Если для временного отображения идеально подходит объект ДеревоЗначений, то вопрос постоянного хранения такой структуры в базе данных требует более детального анализа. Рассмотрим основные способы реализации деревьев, их преимущества и недостатки, а также разберем алгоритмы оптимизации работы с ними.

Вариант 1: Использование стандартной иерархии справочников

Самый простой и очевидный способ — использование встроенного механизма платформы. Справочники в 1С поддерживают иерархию (типа «иерархия элементов» или «иерархия групп и элементов»). Это готовое дерево, где у каждого элемента есть реквизит Родитель.

Проанализируем этот подход. Платформа берет на себя все заботы по контролю целостности, исключению циклов (когда элемент становится родителем самого себя) и визуализации в списках. Однако у этого метода есть ограничения. Если дерево должно быть частью документа или данные очень динамичны, справочник может «раздуваться», что со временем приведет к падению производительности при поиске и записи.

Рассмотрим, как ограничить глубину дерева, если это необходимо бизнес-логике. Для этого в метаданных справочника мы можем программно контролировать свойство КоличествоУровнейИерархии. Также в запросах для работы с такими структурами мы будем использовать конструкцию В ИЕРАРХИИ, которая позволяет эффективно выбирать все дочерние узлы любой вложенности.

Вариант 2: Сериализация Дерева Значений в Хранилище Значения

Если структура дерева нужна только в контексте конкретного объекта (например, настройки отчета или специфическое дерево в документе) и по его узлам не требуется выполнять поиск через запросы, мы можем использовать сериализацию. Разберем этот алгоритм подробнее:

  1. Создаем объект ДеревоЗначений на сервере.
  2. Заполняем его необходимыми данными.
  3. Помещаем объект в ХранилищеЗначения.
  4. Сохраняем это хранилище в реквизит объекта (справочника или документа).

Посмотрим на пример кода для записи:


// Предположим, ДеревоОбъект — это наше заполненное ДеревоЗначений
НоваяЗапись = Справочники.НастройкиДеревьев.СоздатьЭлемент();
НоваяЗапись.Наименование = "Моя структура";
НоваяЗапись.ДанныеДерева = Новый ХранилищеЗначения(ДеревоОбъект);
НоваяЗапись.Записать();

И пример для чтения:


Запись = Справочники.НастройкиДеревьев.НайтиПоНаименованию("Моя структура");
Если Не Запись.Пустая() Тогда
    ДеревоИзБазы = Запись.ДанныеДерева.Получить();
    // Теперь ДеревоИзБазы можно вывести на форму
КонецЕсли;

Важный нюанс: Этот метод делает данные «невидимыми» для языка запросов. Вы не сможете посчитать сумму по ветке дерева, не считав весь объект целиком в память сервера. Используйте этот способ только для хранения настроек или компактных структур.

Вариант 3: Связанные табличные части с использованием идентификаторов (UUID)

Для документов часто применяют метод «плоского» хранения в табличной части с программной сборкой в дерево при открытии формы. Выясним причину популярности этого метода: он позволяет хранить данные внутри документа, сохраняя возможность их анализа в запросах.

Разберем технологию реализации:

  1. В табличной части создаем реквизит ИдентификаторУзла (тип Строка или УникальныйИдентификатор) и ИдентификаторРодителя.
  2. При чтении документа (в событии ПриЧтенииНаСервере) мы перебираем строки ТЧ и программно строим ДеревоЗначений, сопоставляя родителей и детей.
  3. При записи документа мы выполняем обратную операцию: разворачиваем дерево в плоский список и записываем в табличную часть.

Этот метод хорошо работает для небольших деревьев (2-3 уровня вложенности). Если же уровней много, процесс сборки/разборки может стать ресурсоемким.

Вариант 4: Продвинутые алгоритмы (Nested Sets и Materialized Path)

Для высоконагруженных систем, где чтение дерева происходит в тысячи раз чаще, чем его изменение, мы рекомендуем рассмотреть алгоритмы из области классических БД. В 1С их удобнее всего реализовывать на базе Регистров Сведений.

Materialized Path (Материализованный путь): в каждой записи регистра хранится строка вида 001.005.012. Это полный путь от корня. Проанализируем преимущество: чтобы найти всех потомков узла 001.005, нам достаточно выполнить простой запрос с условием ПОДОБНО "001.005.%". Это работает молниеносно даже на миллионах записей.

Nested Sets (Вложенные множества): каждому узлу присваиваются два числа — левый и правый ключ. Все потомки узла имеют ключи, находящиеся в диапазоне между левым и правым ключом родителя. Это позволяет получать целые ветви одним запросом без рекурсии, но значительно усложняет вставку новых элементов, так как требует пересчета ключей у «соседей».

Оптимизация интерфейса: «Ленивая загрузка»

Если ваше дерево содержит тысячи элементов, попытка загрузить его целиком на управляемую форму приведет к зависанию интерфейса. Рассмотрим, как реализовать динамическую подгрузку данных (Lazy Loading):

  1. При инициализации формы загружаем только первый уровень дерева (корневые узлы).
  2. Для узлов, у которых есть дети, добавляем «пустышку» (фиктивную строку), чтобы у пользователя появился символ «+» (плюсик).
  3. В обработчике события ПриРазворачивании проверяем, загружены ли данные. Если нет — удаляем «пустышку», запрашиваем данные из базы только для этого конкретного узла и добавляем их в дерево.

Посмотрим на пример обработки разворачивания:


&НаСервере
Процедура ПодгрузитьПодчиненныеУзлы(ИдентификаторСтроки)
    ЭлементДерева = ДанныеФормыДерево.НайтиПоИдентификатору(ИдентификаторСтроки);
    // Логика запроса к БД для получения детей
    // ...
    // Заполнение ЭлементДерева.ПолучитьЭлементы()
КонецПроцедуры

Использование JSON для гибких структур

В современных версиях 1С 8.3 (начиная с 8.3.6) появилась отличная поддержка JSON. Если структура вашего дерева постоянно меняется (добавляются новые свойства узлов), хранение дерева в виде JSON-строки в реквизите Строка (неограниченная) может стать отличной альтернативой ХранилищуЗначения.

Преимущества JSON:

Подводя итог, выбор метода зависит от ваших задач. Если нужна простота и стандартные отчеты — выбирайте иерархические справочники. Если дерево является частью документа — используйте табличные части. Если же вы строите сложную аналитическую систему с огромными деревьями — смотрите в сторону регистров сведений с алгоритмом материализованных путей.

← На главную