При интеграции систем или обмене данными через HTTP-сервисы часто возникает задача поиска физических лиц или контрагентов по наименованию или ФИО. Одна из распространенных проблем — различие в написании букв «е» и «ё». Например, в одной базе человек записан как «Секретарев», а из другой приходит «Секретарёв». Прямое сравнение через оператор равенства = в языке запросов 1С не считает такие строки идентичными.
Рассмотрим, как решить эту проблему с помощью встроенных возможностей языка запросов и встроенного языка 1С, а также проанализируем альтернативные архитектурные подходы.
В языке запросов 1С нельзя применить функцию СтрЗаменить() непосредственно к полям таблицы. Однако мы можем подготовить параметр запроса на встроенном языке 1С перед передачей его в запрос, используя возможности оператора ПОДОБНО и квадратные скобки [...], которые означают выбор одного из указанных символов.
Разберем по шагам, как сформировать поисковую строку:
ВРег(), чтобы не завязываться на регистр.[ЕЁ].ПОДОБНО.Посмотрим на пример реализации кода:
// Исходное ФИО, полученное из сторонней системы
ИскомоеФИО = "Секретарев";
// Формируем шаблон для оператора ПОДОБНО
СтрокаПоиска = ВРег(ИскомоеФИО);
СтрокаПоиска = СтрЗаменить(СтрокаПоиска, "Е", "[]");
СтрокаПоиска = СтрЗаменить(СтрокаПоиска, "Ё", "[]");
СтрокаПоиска = СтрЗаменить(СтрокаПоиска, "[]", "[ЕЁ]");
// Выполняем запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ФизическиеЛица.Ссылка КАК Ссылка
|ИЗ
| Справочник.ФизическиеЛица КАК ФизическиеЛица
|ГДЕ
| ВРЕГ(ФизическиеЛица.Наименование) ПОДОБНО &СтрокаПоиска
| И ФизическиеЛица.ДатаРождения = &ДатаРождения";
Запрос.УстановитьПараметр("СтрокаПоиска", СтрокаПоиска);
Запрос.УстановитьПараметр("ДатаРождения", ВходнаяДатаРождения);
РезультатЗапроса = Запрос.Выполнить();
При таком подходе строка "Секретарев" превратится в шаблон "С[ЕЁ]КР[ЕЁ]ТАР[ЕЁ]В". Оператор ПОДОБНО корректно найдет в базе записи с любым сочетанием букв «е» и «ё».
Проанализируем производительность данного решения. Использование масок и условий вида ПОДОБНО или функций вроде ВРЕГ() в секции ГДЕ имеет существенные недостатки на больших объемах данных:
%, подчеркивания _ или квадратные скобки), их необходимо экранировать с помощью ключевого слова СПЕЦСИМВОЛ.Если справочник содержит десятки или сотни тысяч записей, рассмотрим более оптимальные варианты архитектуры:
В объект (например, справочник ФизическиеЛица) добавляется дополнительный реквизит ФИОДляПоиска с включенным свойством Индексировать.
ПередЗаписью модуля объекта исходное ФИО очищается: приводится к верхнему регистру, а все буквы «Ё» заменяются на «Е».ГДЕ ФИОДляПоиска = &ИскомоеФИОНайти.Такой подход позволяет СУБД мгновенно находить нужные записи с использованием индексов.
Механизм полнотекстового поиска 1С автоматически приводит букву «ё» к «е» при построении полнотекстового индекса. Поиск через объект ПолнотекстовыйПоиск.СоздатьСписок() работает быстро и не требует дополнительных манипуляций со строками.