При проектировании метаданных в системе «1С:Предприятие» разработчики часто сталкиваются с ограничением: измерение регистра сведений должно быть атомарным. Это означает, что в одну ячейку (поле) нельзя напрямую поместить коллекцию, такую как СписокЗначений или Массив. Однако задачи, требующие сопоставления одного объекта целому набору других объектов, встречаются повсеместно. Рассмотрим подробнее, почему существует это ограничение и какими способами его можно элегантно обойти.
Проанализируем техническую сторону вопроса. Измерения регистра сведений формируют уникальный ключ записи. На уровне СУБД (SQL Server, PostgreSQL и др.) по этим полям строится индекс. Динамические коллекции 1С являются объектами оперативной памяти и не имеют фиксированного типа данных, который можно было бы однозначно проиндексировать в базе данных. Поэтому платформа 1С строго ограничивает типы измерений ссылочными и примитивными типами.
Разберем самый правильный с точки зрения теории реляционных баз данных подход. Если нам нужно сопоставить «Подразделение-источник» списку из пяти «Подразделений-приемников», мы создаем пять отдельных записей в регистре.
В этом случае структура регистра выглядит следующим образом:
ПодразделениеИсточник (Тип: СправочникСсылка.Подразделения)ПодразделениеПриемник (Тип: СправочникСсылка.Подразделения)Если для одного источника назначено 10 приемников, в регистре будет 10 строк. Рассмотрим преимущества этого метода:
СрезПоследних или выполнить соединение в запросе по любому конкретному подразделению-приемнику.Если по какой-то причине (например, логической группировки) вам необходимо, чтобы одна запись в регистре соответствовала именно целому набору, воспользуемся методом «контейнера». Посмотрим, как это реализовать по шагам:
Справочник.НаборыПодразделений.Состав с реквизитом Подразделение.СправочникСсылка.НаборыПодразделений.Теперь в регистр мы записываем не само подразделение, а ссылку на элемент справочника, внутри которого «упакован» весь список. Проанализируем ситуацию: этот способ удобен, если один и тот же набор подразделений часто повторяется для разных источников. Однако помните о необходимости контроля уникальности — важно не создавать дублирующие наборы с одинаковым составом подразделений.
Выясним причину, по которой иногда выбирают хранение данных в текстовом виде. Если нам не требуется искать записи по конкретному элементу списка внутри запроса, а нужно лишь «прочитать и развернуть» список в коде 1С, можно использовать сериализацию.
Для этого изменим тип измерения на Строка (неограниченной длины или с запасом). Перед записью в регистр преобразуем наш массив в строку JSON:
// Пример записи списка в строку
МассивПриемников = Новый Массив;
МассивПриемников.Добавить(Подразделение1);
МассивПриемников.Добавить(Подразделение2);
ЗаписьРегистра = РегистрыСведений.НастройкиПередачи.СоздатьМенеджерЗаписи();
ЗаписьРегистра.ПодразделениеИсточник = Источник;
// Сериализация в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МассивПриемников);
ЗаписьРегистра.СписокПриемниковJSON = ЗаписьJSON.Закрыть();
ЗаписьРегистра.Записать();
Важно: Этот метод делает невозможным эффективный отбор в запросе по условию «ГДЕ ПодразделениеПриемник = &НужноеПодразделение». Используйте его только для вспомогательных данных.
Если список подразделений не должен участвовать в ключе уникальности (то есть он не является «измерением»), мы можем перенести его в ресурс регистра с типом ХранилищеЗначения. Рассмотрим, как это работает:
В измерении остается только ПодразделениеИсточник. В ресурсе ДанныеПриемников мы храним сериализованный массив. Платформа 1С берет на себя сжатие и хранение этого объекта.
// Пример получения данных
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ДанныеПриемников ИЗ РегистрСведений.НастройкиПередачи ГДЕ ПодразделениеИсточник = &Источник";
// ... выполнение запроса
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
СписокПриемников = Выборка.ДанныеПриемников.Получить(); // Получаем исходный массив
КонецЕсли;
Проанализируем продвинутый, но специфический метод. Если количество подразделений-приемников невелико (например, до 32 или 64), каждому подразделению можно присвоить уникальный номер бита. Тогда список превращается в одно число. Сумма весов выбранных подразделений и будет храниться в измерении.
Например: Подразделение А = 1, Подразделение Б = 2, Подразделение В = 4. Если в списке должны быть А и В, мы запишем число 5 (1+4). В языке запросов 1С работать с битами сложно, но для хранения это самый компактный вариант.
Мы рассмотрели различные подходы к решению задачи. Выбор конкретного метода зависит от ваших требований:
Помните: правильная структура данных в начале разработки избавляет от проблем с производительностью в будущем, когда объем данных в регистре вырастет до миллионов записей.