Почему не работает полнотекстовый поиск в независимом регистре сведений 1С и как это исправить?

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

Разработка современных и производительных конфигураций на платформе 1С:Предприятие 8.3 часто требует внедрения удобных механизмов поиска информации. Одним из таких инструментов является встроенный механизм полнотекстового поиска (ПП). Он позволяет пользователям быстро находить необходимые данные по ключевым словам во всей базе данных или в конкретных объектах метаданных.

Однако при настройке полнотекстового поиска в независимых регистрах сведений разработчики часто сталкиваются с крайне неприятной ситуацией: поиск по справочникам и документам работает безупречно, а вот попытки найти запись в регистре сведений не приносят результатов — поисковая выдача остается абсолютно пустой. При этом все стандартные требования соблюдены: использование индекса включено, сам полнотекстовый индекс регулярно обновляется и находится в актуальном состоянии, данные физически присутствуют в таблице базы данных, а папка с файлами индекса на сервере стабильно растет.

В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем неочевидные архитектурные ограничения платформы 1С и рассмотрим по шагам гарантированные способы восстановления работоспособности полнотекстового поиска в независимых регистрах сведений.

Выясняем причину: почему ломается полнотекстовый поиск?

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

Проблема кроется в использовании типа данных УникальныйИдентификатор (UUID) в качестве ключевого поля (измерения) регистра сведений. Многие разработчики используют UUID для интеграции со сторонними информационными системами или для однозначной идентификации записей в рамках распределенных баз данных.

Но с точки зрения платформы 1С тип УникальныйИдентификатор является специализированным системным типом. Он не относится ни к строкам, ни к числам, ни к классическим объектным ссылкам. Соответственно, платформа технически не может его проиндексировать.

Ситуация усугубляется спецификой регистрации изменений в регистрах сведений:

  1. Для объектных сущностей (справочники, документы) платформа регистрирует изменения в файлах индекса по связке: «числовой идентификатор типа метаданных» + «UUID ссылки». Это позволяет легко однозначно идентифицировать объект.
  2. В регистрах сведений (особенно в независимых) физической ссылки на запись не существует. Каждая запись в таблице базы данных однозначно идентифицируется комбинацией значений всех её ключевых полей (периода и измерений). Этот набор полей формирует так называемый ключ записи — РегистрСведенийКлючЗаписи.

Если хотя бы одно из измерений, входящих в состав ключа записи регистра сведений, имеет неподдерживаемый тип (в нашем случае — УникальныйИдентификатор), платформа теряет возможность корректно сформировать поисковый индекс для этой конкретной строки или восстановить ключ записи из индекса при попытке выдать результат пользователю. Происходит «молчаливый» сбой: физически индекс может строиться, но при запросе система не может вернуть валидный ключ записи и просто отсекает этот результат, возвращая пустой список.

Особенности работы ПП со ссылочными типами данных в регистрах

В процессе обсуждения данной проблемы часто возникает сопутствующий вопрос: будет ли работать полнотекстовый поиск по текстовому представлению (например, наименованию справочника), если в измерении регистра сведений хранится только ссылка на этот справочник, а не текстовая строка?

Давайте проясним этот момент. Полнотекстовый поиск 1С работает со ссылочными типами в регистрах корректно. При индексации полей, содержащих ссылки на другие объекты базы данных, платформа автоматически запрашивает и помещает в поисковый индекс их текстовые представления (для справочников — наименование или код, для документов — представление документа с номером и датой). Таким образом, если в регистре хранится ссылка на справочник «Контрагенты» с наименованием «Альфа-Трейд», то при поисковом запросе «Альфа» запись регистра будет успешно найдена. Проблема возникает исключительно из-за наличия некорректных типов данных в ключевых полях регистра.

Пошаговые варианты решения проблемы

Если перед нами стоит задача сохранить логику работы с уникальными идентификаторами и при этом обеспечить полнотекстовый поиск по регистру, мы можем применить несколько обходных путей.

Способ 1. Замена типа измерения на «Строку» (Рекомендуемый способ)

Самым простым, надежным и быстро реализуемым решением является отказ от использования типа УникальныйИдентификатор в измерениях регистра сведений и замена его на тип Строка фиксированной или переменной длины (длина UUID всегда составляет 36 символов).

Рассмотрим по шагам процесс реализации этого решения:

  1. Откройте конфигуратор и найдите ваш независимый регистр сведений.
  2. Перейдите на вкладку «Данные».
  3. Найдите измерение, содержащее тип УникальныйИдентификатор, и измените его тип на Строка с длиной 36 символов.
  4. В модулях конфигурации, где происходит запись данных в этот регистр, добавьте преобразование UUID в строковое представление с помощью встроенной функции Строка().

Давайте посмотрим на пример кода, выполняющего запись в такой регистр сведений:


// Пример записи данных с преобразованием UUID в строку
НовыйУИД = Новый УникальныйИдентификатор;
СтрокаУИД = Строка(НовыйУИД); // Получаем строковое представление вида "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

МенеджерЗаписи = РегистрыСведений.ИсторияВзаимодействий.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Период = ТекущаяДата();
МенеджерЗаписи.ИдентификаторСтрокой = СтрокаУИД; // Записываем как строку
МенеджерЗаписи.Контрагент = СсылкаНаКонтрагента;
МенеджерЗаписи.Содержание = "Успешный телефонный разговор по проекту.";

МенеджерЗаписи.Записать(Истина);

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


// Обратное преобразование строки из регистра в объект УникальныйИдентификатор
СтроковоеЗначение = ВыборкаИзРегистра.ИдентификаторСтрокой;
Попытка
    ИсходныйУИД = Новый УникальныйИдентификатор(СтроковоеЗначение);
Исключение
    ИсходныйУИД = Неопределено;
    ЗаписатьЛогОшибок("Не удалось преобразовать строку в УникальныйИдентификатор");
КонецПопытки;

Способ 2. Использование служебного справочника

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

Схема реализации выглядит следующим образом:

  1. Создаем новый служебный справочник, например, ВнешниеИдентификаторы.
  2. В качестве длины кода или наименования этого справочника задаем 36 символов, либо добавляем реквизит Идентификатор с типом Строка (длина 36).
  3. В независимом регистре сведений вместо типа УникальныйИдентификатор используем тип СправочникСсылка.ВнешниеИдентификаторы.

Этот способ позволяет платформе беспрепятственно строить полнотекстовый индекс, так как ссылочные типы данных полностью поддерживаются поисковым механизмом 1С.

Программная обработка результатов поиска по регистрам сведений

После того как мы устранили проблему с типами данных и успешно проиндексировали регистр, нам необходимо научиться правильно обрабатывать результаты поиска в программном коде. Важно помнить, что поиск по регистру возвращает специфический объект.

Давайте разберем, что именно возвращает полнотекстовый поиск для разных объектов метаданных:

Начиная с версии платформы 8.3.6, разработчики получили возможность очень просто открывать форму записи регистра сведений по полученному ключу. Мы можем использовать метод глобального контекста ОткрытьЗначение() или метод управляемой формы ПоказатьЗначение().

Проанализируем пример программного кода, который осуществляет полнотекстовый поиск по нашей базе данных и открывает форму найденной записи регистра сведений:


Процедура НайтиИОткрытьЗаписьРегистра(ТекстЗапроса)
    
    // Создаем список полнотекстового поиска
    СписокПоиска = ПолнотекстовыйПоиск.СоздатьСписок(ТекстЗапроса, 10);
    СписокПоиска.ПерваяЧасть();
    
    Если СписокПоиска.ПолноеКоличество() = 0 Тогда
        ПоказатьПредупреждение(, "По вашему запросу ничего не найдено.");
        Возврат;
    КонецЕсли;
    
    // Обходим результаты поиска
    Для Каждого ЭлементПоиска Из СписокПоиска Цикл
        
        ТекущееЗначение = ЭлементПоиска.Значение;
        ТипЗначения = ТипЗнч(ТекущееЗначение);
        
        // Проверяем, является ли найденный объект ключом записи нашего регистра
        Если Найти(Строка(ТипЗначения), "РегистрСведенийКлючЗаписи") > 0 Тогда
            
            // Начиная с 8.3.6, платформа умеет автоматически открывать форму записи по ключу
            ПоказатьЗначение(, ТекущееЗначение);
            Прервать; // Открываем первую найденную запись и завершаем работу
            
        КонецЕсли;
        
    КонецЦикла;
    
КонецПроцедуры

Если ваша конфигурация по какой-то причине работает на старых версиях платформы (ниже 8.3.6), прямая передача ключа записи в метод ОткрытьЗначение() вызовет ошибку. В этом случае нам придется вручную разбирать ключ записи на измерения и открывать форму записи программно, передавая параметры отбора:


// Альтернативный вариант открытия формы для старых версий платформы
ПараметрыОтбора = Новый Структура;
Для Каждого Измерение Из ТекущееЗначение.Метаданные().Измерения Цикл
    ИмяИзмерения = Измерение.Имя;
    ПараметрыОтбора.Вставить(ИмяИзмерения, ТекущееЗначение[ИмяИзмерения]);
КонецЦикла;

ПараметрыФормы = Новый Структура("Key", ПараметрыОтбора);
ОткрытьФорму("РегистрСведений.ИсторияВзаимодействий.ФормаЗаписи", ПараметрыФормы);

Рекомендации по оптимизации и администрированию полнотекстового поиска

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

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

  1. Отключайте полнотекстовый поиск для ненужных полей. По умолчанию при создании новых измерений, ресурсов или реквизитов регистра сведений свойство Полнотекстовый поиск установлено в значение Использовать. Это приводит к раздуванию поискового индекса за счет индексации служебных признаков, флагов типа «Булево» или числовых коэффициентов. Рекомендуется явно устанавливать свойство Полнотекстовый поиск в значение Не использовать для всех полей, по которым пользователи заведомо не будут осуществлять текстовый поиск.
  2. Настройте регламентное задание обновления индекса. Полнотекстовый поиск не будет выдавать актуальные результаты, если индекс устарел. В типовых конфигурациях 1С (на базе БСП) по умолчанию уже настроены два регламентных задания:
    • ОбновлениеИндексаПП (работает с высокой частотой, например, каждые 1-5 минут, выполняя слияние свежих изменений);
    • СлияниеИндексаПП (выполняется реже, например, один раз в сутки, для оптимизации структуры файлов индекса на диске).
    Убедитесь, что в вашей информационной базе эти регламентные задания активны и выполняются без ошибок.
  3. Контролируйте размер каталога индекса. Файлы полнотекстового поиска хранятся в специальном каталоге на сервере приложений 1С:Предприятие. Если размер базы данных велик, не забывайте закладывать достаточное дисковое пространство под индекс ПП на быстрых SSD-накопителях.

Мы подробно разобрали неочевидное поведение платформы 1С при работе с полнотекстовым поиском по регистрам сведений, выявили главного «виновника» пустых результатов в лице типа данных УникальныйИдентификатор и научились правильно проектировать структуру метаданных для бесперебойной работы поиска. Применяя эти знания на практике, вы сможете создавать надежные и быстрые механизмы поиска информации в ваших прикладных решениях.

← На главную