Как в 1С выполнить поиск и отбор строк по нескольким словам с условием «ИЛИ»?

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

При обработке коллекций данных в 1С часто возникает задача: проверить текстовое поле и отобрать только те строки, которые содержат хотя бы одно слово из заданного списка образцов (логическое условие «ИЛИ»). Например, необходимо перебрать строки таблицы значений и перенести в табличную часть документа только те позиции, наименование которых включает «слово1», «слово2» или «слово3».

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

Ограничения стандартного метода НайтиСтроки

Проанализируем базовый инструмент работы с коллекциями — метод ТаблицаЗначений.НайтиСтроки(). Он принимает в качестве параметра структуру отбора, но обладает двумя критическими ограничениями:

  1. Только строгое равенство: метод ищет точное совпадение значения колонки, частичный поиск по подстроке не поддерживается.
  2. Только условие «И»: если передать в структуру несколько ключей, поиск объединит их по логическому «И», а условие «ИЛИ» для нескольких значений одного поля задать невозможно.

Поэтому для нестрогого поиска по списку слов применяются другие подходы.

Вариант 1. Программная проверка в цикле (СтрНайти / Найти)

Рассмотрим самый понятный и быстрый для таблиц в оперативной памяти способ — обход строк в цикле с проверкой вхождения подстрок с помощью встроенной функции СтрНайти() (или Найти() в более ранних версиях платформы).

Разберем по шагам логику работы:

  1. Помещаем искомые слова в массив МассивИскомыхСлов.
  2. Для исключения влияния регистра символов приводим проверяемый текст и образцы к единому регистру с помощью функции ВРЕГ() или НРЕГ().
  3. Во внутреннем цикле проверяем вхождение каждого слова. Как только найдено первое совпадение, прерываем внутренний цикл оператором Прервать, чтобы не тратить процессорное время на оставшиеся слова.
  4. Добавляем найденную строку в приемник (например, табличную часть).

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


МассивИскомыхСлов = Новый Массив;
МассивИскомыхСлов.Добавить("СЛОВО1");
МассивИскомыхСлов.Добавить("СЛОВО2");
МассивИскомыхСлов.Добавить("СЛОВО3");

Для Каждого СтрТЗ Из ТаблицаЗначенийИсточник Цикл
    ТекстДляПроверки = ВРЕГ(СтрТЗ.Наименование);
    СтрокаПодходит = Ложь;
    
    Для Каждого ИскомоеСлово Из МассивИскомыхСлов Цикл
        Если СтрНайти(ТекстДляПроверки, ИскомоеСлово) > 0 Тогда
            СтрокаПодходит = Истина;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    Если СтрокаПодходит Тогда
        НоваяСтрокаТЧ = Объект.Товары.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрокаТЧ, СтрТЗ);
    КонецЕсли;
КонецЦикла;

Вариант 2. Поиск через запрос с использованием ПОДОБНО

Если выборка данных выполняется непосредственно из базы данных (например, из справочника Справочник.Номенклатура) или если таблица значений предварительно передается в запрос как параметр, удобно использовать механизм запросов 1С.

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


// Формируем таблицу параметров со списком слов и масками
ТаблицаСлов = Новый ТаблицаЗначений;
ТаблицаСлов.Колонки.Добавить("Слово", Новый ОписаниеТипов("Строка",,,, Новый КвалификаторыСтроки(150)));

НоваяСтрока = ТаблицаСлов.Добавить();
НоваяСтрока.Слово = "%Слово1%";

НоваяСтрока = ТаблицаСлов.Добавить();
НоваяСтрока.Слово = "%Слово2%";

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

Запрос.УстановитьПараметр("ТаблицаСлов", ТаблицаСлов);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    НоваяСтрокаТЧ = Объект.Товары.Добавить();
    НоваяСтрокаТЧ.Номенклатура = Выборка.Ссылка;
КонецЦикла;

Обратим внимание на важные детали запроса:

  1. Ключевое слово РАЗЛИЧНЫЕ: если строка удовлетворяет сразу нескольким шаблонам (например, содержит и «слово1», и «слово2»), внутреннее соединение вернет дубли. Конструкция РАЗЛИЧНЫЕ исключает дублирование записей в результате.
  2. Регистронезависимость: использование функции ВРЕГ() гарантирует корректный поиск вне зависимости от настроек сопоставления (collation) базы данных на стороне СУБД (MS SQL Server, PostgreSQL).

Особенности производительности и альтернативы

Выбирая способ реализации, учитываем следующие особенности:

  1. Сканирование таблиц в СУБД: использование конструкции ПОДОБНО "%значение%" делает невозможным использование индексов и приводит к полному сканированию таблицы (Full Scan). При выборке из справочников с сотнями тысяч записей этот запрос может выполняться медленно.
  2. Специальные символы: если искомое слово содержит знаки %, _, [, ], платформа воспринимает их как спецсимволы шаблона. Для точного поиска таких знаков в запросе применяется экранирование с помощью ключевого слова СПЕЦСИМВОЛ.
  3. Полнотекстовый поиск: если требуется регулярный быстрый поиск по базе данных с учетом морфологии и операторов «ИЛИ», рекомендуется использовать объект ПолнотекстовыйПоиск.СоздатьСписок(), опирающийся на встроенные полнотекстовые индексы платформы 1С.
← На главную