Как в 1С отобрать элементы справочника по вхождению подстроки в наименование

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

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

Почему метод Выбрать() со структурой отбора не подходит для поиска по подстроке

Проанализируем попытку использовать метод СправочникиМенеджер.<Имя>.Выбрать() с передачей структуры отбора. Параметр Отбор этого метода принимает только объект Структура. Платформа 1С накладывает строгое ограничение на такую фильтрацию: все значения, переданные в структуру, проверяются СУБД исключительно на точное равенство.

Использовать в структуре условия вида «Содержит», «Начинается с», диапазоны или маски поиска невозможно. Если передать в структуру строку «Аптечка», система найдет только те элементы, у которых наименование в точности равно «Аптечка», но пропустит элементы вроде «Аптечка автомобильная» или «Футляр для аптечки».

Решение 1. Использование запроса с оператором ПОДОБНО (основной способ)

Самым правильным, быстрым и стандартным способом получения данных по условию вхождения подстроки является объект Запрос. Для поиска по маске в языке запросов 1С используется оператор ПОДОБНО.

Разберем по шагам, как составить и выполнить такой запрос:

  1. Создадим объект Запрос и опишем текст выборки из нужной таблицы справочника.
  2. Установим условие в секции ГДЕ с использованием оператора ПОДОБНО и спецсимволов % (любое количество произвольных символов).
  3. Передадим искомую подстроку через параметры запроса.
  4. Выполним запрос и обойдем результат в цикле.

Посмотрим на пример программного кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Ссылка,
    |	Номенклатура.Наименование КАК Наименование
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.Наименование ПОДОБНО &ШаблонПоиска
    |	И НЕ Номенклатура.ЭтоГруппа";

// Символ % обозначает любую последовательность произвольных символов
Запрос.УстановитьПараметр("ШаблонПоиска", "%" + "Аптечка" + "%");

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    Сообщить(Выборка.Наименование);
КонецЦикла;

Важный нюанс производительности: при поиске по шаблону "%Текст%" символ процента в начале строки не позволяет СУБД задействовать индекс по полю Наименование. Это приводит к полному сканированию таблицы базы данных (Full Scan). Если поиск требуется выполнять только по началу наименования (шаблон "Аптечка%"), СУБД сможет использовать индекс, что в разы ускорит выполнение на больших объемах данных.

Решение 2. Программный обход выборки с фильтрацией через функцию СтрНайти()

Если по каким-то причинам требуется обойтись без написания запроса (например, в простой внешней обработке при небольшом общем количестве записей в справочнике), можно выбрать все элементы и отфильтровать их встроенным языком с помощью функции СтрНайти().

Посмотрим на пример реализации:


ВыборкаНоменклатура = Справочники.Номенклатура.Выбрать();

Пока ВыборкаНоменклатура.Следующий() Цикл
    // Проверяем наличие подстроки в наименовании текущего элемента
    Если СтрНайти(ВыборкаНоменклатура.Наименование, "Аптечка") > 0 Тогда
        Сообщить(ВыборкаНоменклатура.Наименование);
    КонецЕсли;
КонецЦикла;

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

Решение 3. Установка отбора в динамическом списке (для интерфейса)

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

Разберем установку такого отбора в коде формы:


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

Решение 4. Использование механизма полнотекстового поиска

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


СписокПоиска = ПолнотекстовыйПоиск.СоздатьСписок("Аптечка*", 20);
СписокПоиска.ОбластьПоиска.Добавить(Метаданные.Справочники.Номенклатура);
СписокПоиска.ПерваяЧасть();

Для Каждого Результат Из СписокПоиска Цикл
    НайденнаяСсылка = Результат.Значение;
    Сообщить(НайденнаяСсылка);
КонецЦикла;

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

← На главную