Почему полнотекстовый поиск в 1С не находит документы по номеру с частью лидирующих нулей?

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

При работе в типовых конфигурациях 1С пользователи часто сталкиваются с нестандартным поведением строки поиска в динамических списках. Например, если у документа номер имеет вид ПРЕФ-000070, то при вводе в строку поиска значения 70 документ находится, при вводе полного номера с нулями 000070 — также находится. Однако при попытке найти документ по запросу 070 или 0070 поиск не возвращает никаких результатов. Разберем подробнее, почему так происходит и как с этим работать.

Анализ механизма индексации и токенизации

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

  1. Разбиение на токены: При индексации составных номеров (содержащих префиксы и дефисы, таких как ПРЕФ-000070) символ дефиса расценивается как разделитель. Платформа формирует отдельные лексемы: текстовую часть ПРЕФ и числовую часть 000070.
  2. Нормализация чисел: Числовые значения сохраняются в полнотекстовом индексе сразу в двух представлениях: в исходном строковом виде с нулями (000070) и в виде нормализованного числа без лидирующих нулей (70).
  3. Префиксный поиск по словарям: Механизм полнотекстового поиска по умолчанию ищет совпадения только с начала лексемы (по шаблону слово*). Поиск внутри слова или с произвольной позиции не выполняется.

Рассмотрим, как движок обрабатывает различные варианты поисковых запросов:

  1. Запрос 70: Система находит совпадение с нормализованным числовым токеном 70, и документ отображается в списке.
  2. Запрос 000070: Система успешно совпадает с началом исходного строкового токена 000070.
  3. Запросы 070 или 0070: Совпадений не происходит. Строковый токен в индексе начинается с 0000..., а не с 070.... Поисковый движок не производит поиск по произвольной подстроке внутри лексемы.

Различие между полнотекстовым поиском и стандартным поиском по строкам

Посмотрим на разницу между строкой поиска динамического списка и обычным поискам по контексту. Поиск по комбинации клавиш Alt + F не задействует полнотекстовый индекс. Это банальный отбор по отображаемым строкам непосредственно в представлении таблицы на клиенте или через СУБД с оператором ПОДОБНО '%...'. Поэтому поиск через Alt + F находит подстроки с любым количеством нулей, тогда как строка поиска списка применяет механизмы ППД.

Варианты решения и обхода ограничения

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

1. Использование стандартных отборов вместо глобальной строки поиска

Выясним, как пользователи могут находить нужные документы без изменения конфигурации:

  1. Использовать стандартный поиск по конкретной колонке «Номер» (через контекстное меню или горячие клавиши) с режимом сравнения Содержит.
  2. Настроить отбор динамического списка через меню Еще — Настроить список, добавив условие по полю Номер с видом сравнения Содержит.

2. Отключение полнотекстового поиска для объекта

Если отключить полнотекстовый поиск для конкретного документа или реквизита в конфигураторе (либо полностью отключить ППД в администрировании базы данных), строка поиска в динамическом списке перестанет использовать полнотекстовый индекс. В этом случае система начнет выполнять фильтрацию непосредственно через SQL-запросы с использованием условия ПОДОБНО '%...'. Это позволит искать номера вида 070 и 0070, однако на больших объемах данных может снизиться скорость выполнения запросов.

3. Программная адаптация поля поиска в форме

Для программистов 1С доступен вариант перехвата ввода строки поиска. Рассмотрим пример, когда при изменении текста в поле поиска устанавливается отбор динамического списка без применения полнотекстового индекса:


&НаСервере
Процедура УстановитьОтборПоНомеруНаСервере(ТекстПоиска)
    
    ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение = Новый СомпоновкаДанныхПоле("Номер");
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;
    ЭлементОтбора.ПравоеЗначение = ТекстПоиска;
    ЭлементОтбора.Использование = Истина;
    
КонецПроцедуры

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

← На главную