Поиск по словам. Вариант сопоставления наименований из набора слов при загрузке внешних данных

09.02.26

Интеграция - Распознавание документов и образов

Рано или поздно каждый 1С-специалист может столкнуться с фактически нерешаемой задачей: организацией загрузки из файла контрагента, где данные предлагается синхронизировать по строке, например, наименованию номенклатуры. Зачастую это строковое представление лишь отдаленно напоминает наименование из соответствующего справочника информационной базы заказчика. То есть фактически контрагент произвольно излагает своё желание, а заказчик требует автоматизировать процесс сопоставления. Надо понимать, что 100% решения задачи не существует. Например, если при анализе примеров стало понятно, что клиентам несвойственна грамотность, лучше вообще не браться за такую автоматизацию. Тем не менее, задачу сопоставления строки из последовательности слов с наименованиями из справочника, где порядок слов может различаться, автору удалось решить в приемлемом для заказчика виде. Предлагаются формулировка условий задачи и подходы к реализации решения

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

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

В общем случае приемлемым является вариант, когда в результате поиска формируется список "похожих" результатов, который предлагается пользователю для окончательного выбора(сопоставления). Этот список должен содержать элементы, действительно близкие к запрашиваемому результату. Такой список не должен быть неоправданно большим. По договоренности, при нахождении результата поиска, близкого к 100%-му соответствию с искомым словом, можно осуществлять сопоставление без участия оператора. 

 

Сужение рамок поиска


При построении схемы решения следует заранее определиться с правилами и ограничениями.
Одним из важнейших вопросов является обязательность учета регистра строк – то есть необходимость различия прописных и строчных букв, другим словами, принять решение, можно ли считать ли одинаковыми слова "Молоко" и "МОЛОКО". Как правило, учитывать регистр не требуется, в этом случае поиск требуется осуществлять с преобразованием строк в верхний (нижний) регистры. Такое же преобразование следует проводить и для объектов ИБ, по которым осуществляется поиск, например, наименовании номенклатуры. Удобно использовать, например, функцию ВРЕГ() встроенного языка платформы, а начиная с релиза Платформы 8.3.20 аналогичная функция присутствует и в языке запросов, что значительно поможет в решении.

Также необходимо определиться с необходимостью четкостью поиска: ищем только по полным словам или подстрокам(на вхождение). Может потребоваться, например, при поиске по слову «шоколад», включать позиции, содержащие в наименовании слово «шоколадный». Но нужно понимать, что такой подход может таить не видимые на первый взгляд неточности. Например, при англоязычном поиске мы столкнулись с выдачей в результаты наименование Pinapple(ананас) при поиске по строке Apple(яблоко), что не совсем верно. 

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

Кроме того, полезно определиться с достаточным процентом совпадения слов строки. Если для принятия решение о совпадении строки из двух строк необходимо наличие пересечения обоих слов, то для строки, например, из пятнадцати слов, может быть достаточно четырнадцати или меньшего количества. 

 

Подготовка массива строк


Для разложения строки на массив слов требуется определится с разделителем слов. Удобно использовать пробел. Тогда нужно избавиться от остальных небуквенных символов, включая знаки препинания, «.,;кавычки» и пр. пр., а так же удвоенных пробелов и переносов строк, например через

ПоисковаяСтрока = СтрЗаменить(ПоисковаяСтрока,”,”, ””)


Таким же способом можно исключить предлоги и союзы, чтобы в поиске участвовали только слова, несущие основную смысловую нагрузку. К "лишним" словам зачастую можно отнести и упоминание упаковок/тары (например, "банка 800 гр. стекло").

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

МассивСлов = СтрРазделить(ПоисковаяСтрока, ” ”)


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

Дополнительно может возникнуть задача последующего контроля итоговых результатов поиска на предмет явного "мусора". Кроме того, если возможно, при поиске на вхождение(подстроке), следует осуществлять проверку на несинонимичные и противоречивые результаты , например, «килограмм» при поиске слова "грамм" или "нестерильный" вместо "стерильный".


Построение запроса для одной строки


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

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

Поиск по массиву исходных строк


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

Для Каждого ИсходнаяСтрока Из МассивСтрок Цикл

      МассивСлов = СтрРазделить(ИсходнаяСтрока , ” ”);

      Запрос.Текст = Запрос.Текст + ?(Запрос.Текст = "", "", " ОБЪЕДИНИТЬ ВСЕ ");


      //здесь код построения запроса по одной строке (пример выше)

КонецЦикла;


 

При этом для последующего разбора результатов можно дополнить запрос колонкой указанием исходной строки поиска, например

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


    При построения текста запроса в цикле для каждой искомой строки значение параметра должно быть уникальным. Можно использовать номер по порядку

Н = 0;

Для Каждого ИсходнаяСтрока Из МассивСтрок Цикл
      Н = Н + 1;

//..........
				"ВЫБРАТЬ
				|	Номенклатура.Ссылка Как Номенклатура,
                                |	&ИсходнаяСтрока "+Н+" Как ИсходнаяСтрока 
				|ИЗ
				|	Справочник.Номенклатура КАК Номенклатура
				|ГДЕ";
//.....................
      Запрос.УстановитьПараметр("ИсходнаяСтрока"+Н, ИсходнаяСтрока) 
//..........

КонецЦикла;


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

Номенклатура ИсходнаяСтрока
Молоко сгущенное, 300 гр Молоко сгущенное
Молоко сгущенное с сахаром, 300 гр Молоко сгущенное
Сахарный песок, 1 кг Песок сахарный
Хлеб ржаной, буханка Хлеб
Хлеб белый пшеничный, батон Хлеб

 

Из примера в таблице видно, что при поиске трех строк запрос возвратил 5 позиций номенклатуры. Для одной из них соответствие найдено точно (один результат), а для двух остальных позиций найдено по 2 варианта, которые следует предложить пользователю для точного сопоставления.

 

Сохранение истории поиска


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

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

Например, пользователь каким-то способом выяснил, что под строкой «макароны Италия» клиент имел в виду какую-то конкретную марку макарон, удобно сохранить пару «исходная строка – элемент справочника», чтобы избавить пользователя от последующего сопоставления строки «макароны Италия».

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

При этом такая задача может иметь дополнительное условие: привязка пары «исходная строка – элемент справочника» к конкретному клиенту. Действительно, под теми же «макаронами Италия» разные клиенты могут понимать разные позиции нашего каталога, и использовать одно и тоже сопоставление для всех клиентов нельзя.

Тогда структуру «исторического» регистра сведений нужно дополнить измерением Партнер/Контрагент.

Например, если на прошлом этапе при загрузке данных от клиента "Наш клиент", оператор сделал сопоставление каждой строки с элементом справочника. Тогда должны быть сформированы 3 записи записи в таблицу регистра сведений 

ИсходнаяСтрока

(измерение)

Контрагент

(измерение)

Номенклатура

(ресурс)

Молоко сгущенное Наш клиент Молоко сгущенное с сахаром, 300 гр
Песок сахарный Наш клиент Сахарный песок, 1 кг
Хлеб Наш клиент Хлеб ржаной, буханка

 

В дальнейшем при поиске с использованием этого Регистра сведений, следует начинать поиск в данном РС путем сравнения исходной строки с соответствующим изменением.

Для оптимизации поиска имеет смысл включить индексирование по измерению ИсходнаяСтрока.

 

Использование предварительного индексирования


Представленная выше структура поискового запроса далека от совершенства, громоздка, неоптимальна и может использоваться лишь ограниченно.

Возможно применение более технологически сложного но и ресурсоёмкого способа – отдельного хранения слов(частей наименования) для каждого элемента справочника.

Для реализации потребуется отдельный регистр сведений с двумя измерениями: Элемент справочника и слово.

Например, для товара «Свинина тушеная ГОСТ» потребуется 3 записи в с такой регистр сведений (без учета регистра)
 

Свинина тушеная ГОСТ СВИНИНА
Свинина тушеная ГОСТ ТУШЕНАЯ
Свинина тушеная ГОСТ ГОСТ

 

Записи в РС удобно проводить в обработчике событий записи элемента номенклатуры (для групп не потребуется, если это отдельно не оговорено в задании) или периодически регламентным заданием. 

Задание может содержать дополнительное требование о порядке выдачи результатов по порядку следования слов.

Например, при поиске по строке "Свинина тушеная ГОСТ" первой должна выдаваться номенклатура "Свинина тушеная ...", а далее "Тушеная свинина ...".

Для реализации такой подзадачи вышеуказанный регистр сведений рекомендуется дополнить ресурсом Порядок типа Число.

Свинина тушеная ГОСТ СВИНИНА 1
Свинина тушеная ГОСТ ТУШЕНАЯ 2
Свинина тушеная ГОСТ ГОСТ 3

При выдаче результатов потребуется отсортировать их по значению ресурса Порядок.

 

Примерный порядок построения поискового запроса с использованием дополнительных инструментов

 

1. Предварительно сформированная таблица значений с колонками Исходная строка, Слово + дополнительная информация при необходимости выгружается во временную таблицу.

2. Если используется РС для записи истории потребуется "соединяться" с ним по поисковой строке в отдельной временной таблице или совместно с РС "индексов"

3. Внутреннее соединение с РС "индексов" по полю Слова. Дополнительно наложить отбор по группе/иерархии (если используется). Сортировка по "порядку", если требуется.

Если решено вести поиск по вхождению(подстроке), тогда условием соединения будет не равно, а подобно, предварительно дополнив слова соответствующими литералами. Например, символами "%" слева и справа.

4. Сгруппировать полученную таблицу по искомой строке для подсчета количества найденных слов.

5. Сгруппировать полученную таблицу для подсчета общего количества слов для каждой из найденных позиций номенклатуры из РС "индексов". Отдельно путем группирования исходной таблицы рассчитываем общее количество слов для каждой искомой строки.

6. Путем соединения полученных таблиц с таблицей полученной на шаге 3, для каждой исходной строки сличаем общее количество слов для строки с количеством успешно сопоставленных строк. Далее необходимо отфильтровать результаты в соответствии с используемым правилом поиска количества. Возможные варианты: точное совпадение(равное количество "пересекающихся" слов и суммарного количества), соответствие с заданным процентом (предыдущий вариант с корректировкой на коэффициент), с заранее определенным минимумом (например 3 слова).

Если используется порядок, дополнительно применяется сортировка по нему.

Отдельной подзадачей, возникшей в ходе нашего "поискового" проекта, стало ограничение выдачи результатов по максимальному количеству найденных слов.

Например, при поиске "Молоко сгущенное с сахаром", в справочнике нашлась номенклатура, содержащая 2 пересекающихся слова, которые попали в выдачу для пользователя:

"Молоко сгущенное вареное"

"Молоко концентрированное с сахаром".

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

Реализация такого условие потребовало небольшой доработки запроса.

 

На этом пока всё. Спасибо тем, кто дочитал до конца. При возникновении интереса буду рад поделиться конкретикой по отдельным вопросам.

Всё описанное можно реализовать на базе любой типовой или авторской конфигурации. Версия применяемой платформы не важна. Но на версиях младших 8.3.20 придется обходиться без функции ВРЕГ() в запросе. А до версии 8.3.6 недоступна функция СтрРазделить(), которая, впрочем, реализована в БСП или может быть написана на встроенном языке самостоятельно.

Вступайте в нашу телеграмм-группу Инфостарт

См. также

SALE! 30%

Распознавание документов и образов Бухгалтер Пользователь 1С 8.3 1С:Бухгалтерия 3.0 Россия Абонемент ($m)

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

1 стартмани

05.02.2026    299    4    user213093test    0    

2

Распознавание документов и образов Программист Пользователь 1С 8.3 1С:Розница 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Абонемент ($m)

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

2 стартмани

19.12.2025    2383    5    kras_71    24    

12

Распознавание документов и образов Программист Пользователь 1С:Предприятие 8 Россия Абонемент ($m)

Решение на платформе 1С для автоматической расшифровки голосовых сообщений из Telegram. Система отслеживает новые аудио в чат-боте, передает их на локальный сервер с Whisper для преобразования в текст и автоматически возвращает готовую транскрипцию обратно в чат. Должна работать на любой конфигурации 1С. Пригодится для энтузиастов и разработчиков интеграций 1С и ИИ.

1 стартмани

25.11.2025    864    2    marat987654321    2    

3

Нейросети Распознавание документов и образов Программист 1С:Предприятие 8 Россия Абонемент ($m)

Статья описывает практический подход к автоматизации сравнения документов с применением технологий OCR и локальных языковых моделей. Рассматриваются этапы настройки и интеграции Tesseract OCR, LM Studio и внешней обработки 1С для создания автономного решения.

1 стартмани

20.11.2025    3269    prokhodolya    5    

19

Учет документов Распознавание документов и образов Бухгалтер Пользователь 1С 8.3 1С:Управление торговлей 11 Платные (руб)

СканДок — это «сканер в смартфоне» для 1С. Вложение файлов в документы 1С за 30–60 секунд без очереди к сканеру и без поиска файлов по папкам.

61000 руб.

24.10.2025    1128    0    0    

0
Для отправки сообщения требуется регистрация/авторизация