Разработка современных и производительных конфигураций на платформе 1С:Предприятие 8.3 часто требует внедрения удобных механизмов поиска информации. Одним из таких инструментов является встроенный механизм полнотекстового поиска (ПП). Он позволяет пользователям быстро находить необходимые данные по ключевым словам во всей базе данных или в конкретных объектах метаданных.
Однако при настройке полнотекстового поиска в независимых регистрах сведений разработчики часто сталкиваются с крайне неприятной ситуацией: поиск по справочникам и документам работает безупречно, а вот попытки найти запись в регистре сведений не приносят результатов — поисковая выдача остается абсолютно пустой. При этом все стандартные требования соблюдены: использование индекса включено, сам полнотекстовый индекс регулярно обновляется и находится в актуальном состоянии, данные физически присутствуют в таблице базы данных, а папка с файлами индекса на сервере стабильно растет.
В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем неочевидные архитектурные ограничения платформы 1С и рассмотрим по шагам гарантированные способы восстановления работоспособности полнотекстового поиска в независимых регистрах сведений.
Давайте проанализируем, как устроен механизм индексации полнотекстового поиска в системе 1С:Предприятие. Согласно официальной технической документации, платформа поддерживает индексацию реквизитов только ограниченного набора типов данных:
Строка (любой длины);Число;Дата;ХранилищеЗначения (если внутри хранятся текстовые данные или файлы поддерживаемых форматов).Проблема кроется в использовании типа данных УникальныйИдентификатор (UUID) в качестве ключевого поля (измерения) регистра сведений. Многие разработчики используют UUID для интеграции со сторонними информационными системами или для однозначной идентификации записей в рамках распределенных баз данных.
Но с точки зрения платформы 1С тип УникальныйИдентификатор является специализированным системным типом. Он не относится ни к строкам, ни к числам, ни к классическим объектным ссылкам. Соответственно, платформа технически не может его проиндексировать.
Ситуация усугубляется спецификой регистрации изменений в регистрах сведений:
РегистрСведенийКлючЗаписи.Если хотя бы одно из измерений, входящих в состав ключа записи регистра сведений, имеет неподдерживаемый тип (в нашем случае — УникальныйИдентификатор), платформа теряет возможность корректно сформировать поисковый индекс для этой конкретной строки или восстановить ключ записи из индекса при попытке выдать результат пользователю. Происходит «молчаливый» сбой: физически индекс может строиться, но при запросе система не может вернуть валидный ключ записи и просто отсекает этот результат, возвращая пустой список.
В процессе обсуждения данной проблемы часто возникает сопутствующий вопрос: будет ли работать полнотекстовый поиск по текстовому представлению (например, наименованию справочника), если в измерении регистра сведений хранится только ссылка на этот справочник, а не текстовая строка?
Давайте проясним этот момент. Полнотекстовый поиск 1С работает со ссылочными типами в регистрах корректно. При индексации полей, содержащих ссылки на другие объекты базы данных, платформа автоматически запрашивает и помещает в поисковый индекс их текстовые представления (для справочников — наименование или код, для документов — представление документа с номером и датой). Таким образом, если в регистре хранится ссылка на справочник «Контрагенты» с наименованием «Альфа-Трейд», то при поисковом запросе «Альфа» запись регистра будет успешно найдена. Проблема возникает исключительно из-за наличия некорректных типов данных в ключевых полях регистра.
Если перед нами стоит задача сохранить логику работы с уникальными идентификаторами и при этом обеспечить полнотекстовый поиск по регистру, мы можем применить несколько обходных путей.
Самым простым, надежным и быстро реализуемым решением является отказ от использования типа УникальныйИдентификатор в измерениях регистра сведений и замена его на тип Строка фиксированной или переменной длины (длина UUID всегда составляет 36 символов).
Рассмотрим по шагам процесс реализации этого решения:
УникальныйИдентификатор, и измените его тип на Строка с длиной 36 символов.Строка().Давайте посмотрим на пример кода, выполняющего запись в такой регистр сведений:
// Пример записи данных с преобразованием UUID в строку
НовыйУИД = Новый УникальныйИдентификатор;
СтрокаУИД = Строка(НовыйУИД); // Получаем строковое представление вида "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
МенеджерЗаписи = РегистрыСведений.ИсторияВзаимодействий.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Период = ТекущаяДата();
МенеджерЗаписи.ИдентификаторСтрокой = СтрокаУИД; // Записываем как строку
МенеджерЗаписи.Контрагент = СсылкаНаКонтрагента;
МенеджерЗаписи.Содержание = "Успешный телефонный разговор по проекту.";
МенеджерЗаписи.Записать(Истина);
При чтении данных из регистра или при необходимости передать строковый идентификатор обратно во внешнюю систему в формате UUID, мы можем легко выполнить обратное преобразование:
// Обратное преобразование строки из регистра в объект УникальныйИдентификатор
СтроковоеЗначение = ВыборкаИзРегистра.ИдентификаторСтрокой;
Попытка
ИсходныйУИД = Новый УникальныйИдентификатор(СтроковоеЗначение);
Исключение
ИсходныйУИД = Неопределено;
ЗаписатьЛогОшибок("Не удалось преобразовать строку в УникальныйИдентификатор");
КонецПопытки;
Если для вашей системы критически важно сохранять ссылочную целостность данных на уровне СУБД, или если вы хотите избежать ручного преобразования типов в коде при связывании таблиц, можно применить архитектурный паттерн со служебным справочником.
Схема реализации выглядит следующим образом:
ВнешниеИдентификаторы.Идентификатор с типом Строка (длина 36).УникальныйИдентификатор используем тип СправочникСсылка.ВнешниеИдентификаторы.Этот способ позволяет платформе беспрепятственно строить полнотекстовый индекс, так как ссылочные типы данных полностью поддерживаются поисковым механизмом 1С.
После того как мы устранили проблему с типами данных и успешно проиндексировали регистр, нам необходимо научиться правильно обрабатывать результаты поиска в программном коде. Важно помнить, что поиск по регистру возвращает специфический объект.
Давайте разберем, что именно возвращает полнотекстовый поиск для разных объектов метаданных:
ЭлементСпискаПолнотекстовогоПоиска.Значение является непосредственно объектная ссылка (СправочникСсылка или ДокументСсылка).РегистрСведенийКлючЗаписи. Он содержит в себе значения всех измерений и период (если регистр периодический), однозначно определяющие конкретную строку.Начиная с версии платформы 8.3.6, разработчики получили возможность очень просто открывать форму записи регистра сведений по полученному ключу. Мы можем использовать метод глобального контекста ОткрытьЗначение() или метод управляемой формы ПоказатьЗначение().
Проанализируем пример программного кода, который осуществляет полнотекстовый поиск по нашей базе данных и открывает форму найденной записи регистра сведений:
Процедура НайтиИОткрытьЗаписьРегистра(ТекстЗапроса)
// Создаем список полнотекстового поиска
СписокПоиска = ПолнотекстовыйПоиск.СоздатьСписок(ТекстЗапроса, 10);
СписокПоиска.ПерваяЧасть();
Если СписокПоиска.ПолноеКоличество() = 0 Тогда
ПоказатьПредупреждение(, "По вашему запросу ничего не найдено.");
Возврат;
КонецЕсли;
// Обходим результаты поиска
Для Каждого ЭлементПоиска Из СписокПоиска Цикл
ТекущееЗначение = ЭлементПоиска.Значение;
ТипЗначения = ТипЗнч(ТекущееЗначение);
// Проверяем, является ли найденный объект ключом записи нашего регистра
Если Найти(Строка(ТипЗначения), "РегистрСведенийКлючЗаписи") > 0 Тогда
// Начиная с 8.3.6, платформа умеет автоматически открывать форму записи по ключу
ПоказатьЗначение(, ТекущееЗначение);
Прервать; // Открываем первую найденную запись и завершаем работу
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Если ваша конфигурация по какой-то причине работает на старых версиях платформы (ниже 8.3.6), прямая передача ключа записи в метод ОткрытьЗначение() вызовет ошибку. В этом случае нам придется вручную разбирать ключ записи на измерения и открывать форму записи программно, передавая параметры отбора:
// Альтернативный вариант открытия формы для старых версий платформы
ПараметрыОтбора = Новый Структура;
Для Каждого Измерение Из ТекущееЗначение.Метаданные().Измерения Цикл
ИмяИзмерения = Измерение.Имя;
ПараметрыОтбора.Вставить(ИмяИзмерения, ТекущееЗначение[ИмяИзмерения]);
КонецЦикла;
ПараметрыФормы = Новый Структура("Key", ПараметрыОтбора);
ОткрытьФорму("РегистрСведений.ИсторияВзаимодействий.ФормаЗаписи", ПараметрыФормы);
Запуск и поддержка полнотекстового поиска на высоконагруженных или больших базах данных требуют от разработчика и администратора соблюдения определенных правил гигиены базы данных.
Рассмотрим ключевые рекомендации, которые позволят минимизировать нагрузку на сервер и ускорить поиск:
Полнотекстовый поиск установлено в значение Использовать. Это приводит к раздуванию поискового индекса за счет индексации служебных признаков, флагов типа «Булево» или числовых коэффициентов. Рекомендуется явно устанавливать свойство Полнотекстовый поиск в значение Не использовать для всех полей, по которым пользователи заведомо не будут осуществлять текстовый поиск.ОбновлениеИндексаПП (работает с высокой частотой, например, каждые 1-5 минут, выполняя слияние свежих изменений);СлияниеИндексаПП (выполняется реже, например, один раз в сутки, для оптимизации структуры файлов индекса на диске).Мы подробно разобрали неочевидное поведение платформы 1С при работе с полнотекстовым поиском по регистрам сведений, выявили главного «виновника» пустых результатов в лице типа данных УникальныйИдентификатор и научились правильно проектировать структуру метаданных для бесперебойной работы поиска. Применяя эти знания на практике, вы сможете создавать надежные и быстрые механизмы поиска информации в ваших прикладных решениях.