Как сделать поиск по справочнику и в запросах 1С 8.3

· 9 мин

Содержание

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

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

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

В любой форме списка поиск работает сразу, кода писать не нужно.

  • Поиск по текущей колонке. Кликните заголовок нужной колонки и начните набирать текст — список отфильтруется по совпадению. Это самый быстрый способ найти элемент по наименованию или коду.
  • Строка поиска. Нажмите Ctrl+F или команду поиска в командной панели списка (значок с лупой). Появится поле ввода: вводите фрагмент, список показывает только подходящие строки. Поиск идёт по видимым колонкам.
  • Отбор списка. Команда Еще → Настроить список → Отбор позволяет задать условие вручную: равно, содержит, в списке. Отбор сохраняется в настройках формы и переживает перезапуск.

Если поиск по колонке находит не то, проверьте, не включён ли уже отбор: он сужает выборку ещё до того, как вы начали искать.

Отдельный нюанс — иерархические справочники (номенклатура, подразделения). По умолчанию поиск идёт внутри открытой группы. Чтобы искать по всему справочнику сразу, переключите список в линейный вид: команда Еще → Режим просмотра → Список убирает дерево групп, и поиск охватывает все элементы.

Этого хватает для повседневной работы пользователя. Программировать приходится, когда поиск нужен нестандартный: по нескольким полям одновременно, с подсказками или по большому объёму данных.

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

Задача: ввёл строку — нашлись контрагенты, у которых совпадает наименование или ИНН или код. Обычный отбор динамического списка соединяет условия через «И», поэтому для поиска «или по одному, или по другому полю» задают произвольный запрос списка с параметром.

В обработчике ПриСозданииНаСервере переводим список на произвольный запрос:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Список.ПроизвольныйЗапрос = Истина;
    Список.ТекстЗапроса =
        "ВЫБРАТЬ
        |   Контрагенты.Ссылка        КАК Ссылка,
        |   Контрагенты.Наименование  КАК Наименование,
        |   Контрагенты.ИНН           КАК ИНН,
        |   Контрагенты.Код           КАК Код
        |ИЗ
        |   Справочник.Контрагенты КАК Контрагенты
        |ГДЕ
        |   Контрагенты.Наименование ПОДОБНО &Строка
        |   ИЛИ Контрагенты.ИНН ПОДОБНО &Строка
        |   ИЛИ Контрагенты.Код ПОДОБНО &Строка";
    Список.Параметры.УстановитьЗначениеПараметра("Строка", "%");
КонецПроцедуры

На форму добавляем реквизит СтрокаПоиска (тип «Строка») и одноимённое поле ввода. В обработчике его изменения передаём значение в параметр запроса, обрамляя процентами:

&НаКлиенте
Процедура СтрокаПоискаПриИзменении(Элемент)
    УстановитьПоиск(СтрокаПоиска);
КонецПроцедуры

&НаСервере
Процедура УстановитьПоиск(Текст)
    Список.Параметры.УстановитьЗначениеПараметра("Строка", "%" + Текст + "%");
КонецПроцедуры

Оператор ПОДОБНО — это аналог LIKE в SQL. Знак % заменяет любое число символов, _ — ровно один. Шаблон %текст% находит вхождение в любом месте строки.

Если в искомых данных могут встречаться сами символы % и _ (например, в наименовании), экранируйте их: ПОДОБНО &Строка СПЕЦСИМВОЛ "~" и подставляйте в параметр ~%, ~_. Иначе пользовательский % сломает логику шаблона.

По умолчанию ПОДОБНО в большинстве баз сравнивает без учёта регистра, но это зависит от настроек СУБД. Чтобы не гадать, приведите обе стороны к одному регистру через ВРЕГ(): условие ВРЕГ(Контрагенты.Наименование) ПОДОБНО &Строка, а в параметр подставьте ВРег(Текст).

Тот же приём работает не только для списков, но и для поиска в обработке или отчёте: запрос с ПОДОБНО по нескольким полям и параметром строки поиска — универсальная заготовка. Разница лишь в том, куда отдаётся результат: в динамический список формы, в таблицу значений или в дерево. Чтобы совпадения «с начала строки» шли выше, добавьте в запрос вычисляемое поле признака и упорядочивайте по нему.

Полнотекстовый поиск, когда оператора ПОДОБНО уже не хватает

ПОДОБНО ищет по подстроке в конкретных полях. Когда надо искать по всей базе сразу, по комментариям и табличным частям, да ещё и с учётом словоформ — используют встроенный полнотекстовый поиск платформы.

Его сначала готовят:

  1. В свойствах объектов метаданных (справочников, документов) включите реквизиты в полнотекстовый поиск — свойство Полнотекстовый поиск = Использовать.
  2. Разрешите механизм: ПолнотекстовыйПоиск.УстановитьРежимПолнотекстовогоПоиска(РежимПолнотекстовогоПоиска.Разрешить).
  3. Постройте индекс: ПолнотекстовыйПоиск.ОбновитьИндекс(). В рабочей базе это делает регламентное задание, вручную индекс обновляют через Администрирование или код.

Сам поиск выглядит так:

СписокФТ = ПолнотекстовыйПоиск.СоздатьСписок("резиновые сапоги", 20);
СписокФТ.ПерваяЧасть();

Для Сч = 0 По СписокФТ.Количество() - 1 Цикл
    Элемент = СписокФТ.Получить(Сч);
    Сообщить(Элемент.Значение);
КонецЦикла;

Второй параметр СоздатьСписок — размер порции. Полнотекстовый поиск отдаёт результаты частями: ПерваяЧасть(), затем СледующаяЧасть(). Свойство Значение элемента — это ссылка на найденный объект.

Если индекс не построен или устарел, полнотекстовый поиск не найдёт ничего либо выдаст неполный результат — это самая частая причина «поиск не работает ».

Полнотекстовый поиск понимает операторы: кавычки для точной фразы, * для усечения, И/ИЛИ/НЕ для логики, # для нечёткого поиска с опечатками. Это ровно тот случай, когда простым ПОДОБНО не обойтись.

Чтобы показать пользователю не только ссылку, но и фрагмент с подсвеченным совпадением, у списка полнотекстового поиска есть метод получения оформленного результата в виде текста с выделением найденных слов. Это удобно, когда результаты выводятся не в обычный список формы, а в поле HTML-документа — как в глобальном поиске самой платформы.

Автоподбор: поиск с подсказками прямо при вводе

Поля ввода ссылочных типов в 1С уже подсказывают варианты при наборе — это встроенный автоподбор. Для своего поля (например, строки поиска) подсказки делают через событие АвтоПодбор.

На поле ввода назначьте обработчик события «АвтоПодбор»:

&НаКлиенте
Процедура ПолеПоискаАвтоПодбор(Элемент, Текст, ДанныеВыбора,
    Параметры, Ожидание, СтандартнаяОбработка)

    Если Ожидание = 0 Тогда
        // Быстрый выбор без паузы — не дёргаем сервер
        Возврат;
    КонецЕсли;

    Если СтрДлина(Текст) < 2 Тогда
        Возврат; // ждём хотя бы два символа
    КонецЕсли;

    ДанныеВыбора = ПодобратьВарианты(Текст);
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПодобратьВарианты(Текст)
    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ ПЕРВЫЕ 10
        |   Контрагенты.Ссылка        КАК Ссылка,
        |   Контрагенты.Наименование  КАК Наименование
        |ИЗ
        |   Справочник.Контрагенты КАК Контрагенты
        |ГДЕ
        |   Контрагенты.Наименование ПОДОБНО &Текст";
    Запрос.УстановитьПараметр("Текст", Текст + "%");

    Результат = Новый СписокЗначений;
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        Результат.Добавить(Выборка.Ссылка, Выборка.Наименование);
    КонецЦикла;

    Возврат Результат;
КонецФункции

Параметр Ожидание — пауза перед срабатыванием. Пока она равна нулю, пользователь ещё печатает; обращаться к базе на каждый символ не нужно. Поиск по префиксу Текст + "%" (без ведущего %) работает заметно быстрее, потому что может использовать индекс.

Отбирайте ПЕРВЫЕ 10 строк. Выпадающий список на сотни позиций неудобен и грузит сервер при каждом нажатии клавиши.

Морфология: поиск по разным формам слова

ПОДОБНО — это сравнение символов: по запросу «сапог» элемент «сапоги» не найдётся. Чтобы поиск понимал словоформы русского языка, нужна морфология, а её из коробки даёт только полнотекстовый поиск.

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

Если нужно найти слово строго в заданной форме, заключите его в кавычки — тогда морфология для этого слова отключается. Нечёткий поиск с учётом опечаток включается оператором #: запрос #трансформатор найдёт и «транформатор».

Вывод простой: нужна словоформа — это полнотекстовый поиск. Через ПОДОБНО морфологию не сделать, не изобретайте для этого самодельные словари.

Как ускорить поиск в больших базах

На справочнике в сотни тысяч строк разница между правильным и наивным поиском — это секунды против минут. Что влияет сильнее всего:

ПриёмЭффект
Индекс на искомом полеПоиск по префиксу идёт по индексу, а не перебором
Шаблон текст% вместо %текст%Ведущий % отключает индекс — полный перебор таблицы
ВЫБРАТЬ ПЕРВЫЕ NОграничивает выборку, не тянет всю базу в форму
Полнотекстовый поискНа больших объёмах быстрее множества ПОДОБНО
Пауза Ожидание в автоподбореОдин запрос вместо запроса на каждый символ

Главный момент — индексы. Чтобы поиск по реквизиту был быстрым, в конфигураторе у реквизита установите свойство Индексировать = Индексировать (или Индексировать с доп. упорядочиванием, если по полю ещё и сортируете). Если фильтруете часто сразу по двум полям (например, организация + контрагент), помогает не два отдельных индекса, а один составной — его создают через индексы объекта метаданных.

Ещё один резерв — не тянуть в форму лишние колонки. В тексте запроса динамического списка оставляйте только те поля, что реально показываются и участвуют в поиске. Каждая лишняя колонка — это дополнительное соединение и чтение данных на каждое открытие формы.

Шаблон с ведущим процентом %текст% индекс использовать не может в принципе — СУБД вынуждена просмотреть каждую строку. На больших таблицах это и есть причина «тормозит поиск».

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

Какой механизм поиска выбрать под задачу?

Частые ошибки при реализации поиска

Ошибки повторяются от проекта к проекту:

  • ПОДОБНО без процентов. ПОДОБНО &Строка без % — это точное совпадение, а не поиск по части. Процент добавляют в параметр, а не в текст запроса.
  • Ведущий % на большой таблице. Шаблон %текст% отключает индекс. На справочнике в сотни тысяч строк это главный тормоз.
  • Запрос на каждый символ. Без проверки Ожидание в автоподборе сервер получает запрос на каждое нажатие клавиши. Проверяйте паузу и минимальную длину строки.
  • Полнотекстовый индекс не обновлён. Поиск «не находит» часто означает, что индекс не построен или устарел. Проверьте регламентное задание обновления индекса.
  • Регистр. Если поиск в вашей СУБД чувствителен к регистру, нормализуйте обе стороны через ВРЕГ().
  • Неэкранированные спецсимволы. Символы % и _ в искомом тексте без СПЕЦСИМВОЛ ломают шаблон. Для пользовательского ввода экранирование обязательно.
Проверьте себя
Почему поиск по шаблону `%текст%` тормозит на большой базе?
Чем сделать поиск с учётом словоформ (сапог → сапоги)?
Где проверяют паузу перед запросом подсказок?

Частые вопросы

Можно ли искать по нескольким полям без произвольного запроса списка?
Обычный отбор динамического списка соединяет условия через «И», поэтому «наименование ИЛИ ИНН» через него не задать. Нужен произвольный запрос с параметром и ИЛИ в условии.
Чем `ПОДОБНО` отличается от полнотекстового поиска?
ПОДОБНО сравнивает символы в конкретных полях и не понимает словоформы. Полнотекстовый поиск ищет по всей базе, учитывает морфологию и опечатки, но требует включённого и обновлённого индекса.
Почему полнотекстовый поиск ничего не находит?
Чаще всего индекс не построен или устарел. Проверьте, что реквизиты включены в полнотекстовый поиск в метаданных, механизм разрешён, а индекс обновлён регламентным заданием.
Как сделать подсказки при вводе в своём поле?
Назначьте полю ввода обработчик события «АвтоПодбор» и заполняйте параметр ДанныеВыбора списком значений. Запрос стройте по префиксу Текст% и ограничивайте ПЕРВЫЕ 10.
Поиск по подстроке тормозит — что делать?
Если возможно, замените шаблон %текст% на префиксный текст% и проиндексируйте поле. Для поиска вхождения в середину строки на больших данных переходите на полнотекстовый поиск.