Нечёткий поиск строк в 1С через fuzzlink.exe
Короткая инструкция по использованию функции НайтиПохожиеСтроки() для поиска похожих строк с учётом опечаток.
Что делает функция
Функция принимает поисковый запрос и массив строк, передаёт их внешней утилите fuzzlink.exe через временные JSON-файлы и возвращает наиболее похожие совпадения. Полезно для поиска товаров, контрагентов и прочих строк, когда поисковой запрос может быть не точным.
Шаг 1. Подготовка
Поместите fuzzlink.exe в каталог программы, (там, куда указывает КаталогПрограммы()). У меня это "C:\Program Files\1cv8\8.3.25.1286\bin\" Функция вызывает его именно оттуда (либо доработайте как вам удобно).
Шаг 2. Сформируйте массив строк
Соберите строки, среди которых нужно искать. Выгрузите массив строк из запроса или из любого источника данных. Ниже я для примера просто сформирую производный массив данных.
МассивТоваров = Новый Массив;
МассивТоваров.Добавить("Молоко Простоквашино 3.2% 950мл");
МассивТоваров.Добавить("Кефир Простоквашино 1%");
МассивТоваров.Добавить("Сметана Простоквашино 20% 315г");
МассивТоваров.Добавить("Творог Простоквашино 5% 220г");
Шаг 3. Вызовите функцию НайтиПохожиеСтроки()
Запрос = "малако прастоквашино"; // намеренно с опечатками
Результаты = НайтиПохожиеСтроки(Запрос, МассивТоваров, 3);
Где параметры:
- Запрос - это искомая строка (заведомо не точная);
- МассивТоваров - это сформированный массив строк в которых нужно найти наиболее похожие элементы;
- 3 - параметр лимита, какое количество похожих элементов нужно вернуть в результате запроса в порядке убывания.
Шаг 4. Обработайте результат
Для Каждого Элемент Из Результаты Цикл
Сообщить(Строка(Элемент.text) + " ("+Строка(Элемент.score)+"%)" );
КонецЦикла;
Элемент результата имеет следующие поля:
- Элемент.text - это текст найденного элемента;
- Элемент.score - процент схожести (похожести) с искомой строкой;
-
Элемент.index - индекс элемента в Массиве строк;
В итого получим следующий результат:
- Молоко Простоквашино 3.2% 950мл (68%)
- Сметана Простоквашино 20% 315г (68%)
- Кефир Простоквашино 1% (57%)
В порядке наибольшей схожести.
Модуль тестовой обработки
&НаКлиенте
Процедура ТестироватьНечеткийПоиск(Команда)
ТестНечеткогоПоиска();
КонецПроцедуры
&НаСервере
Процедура ТестНечеткогоПоиска() Экспорт
// Массив строк, среди которых ищем
МассивТоваров = Новый Массив;
МассивТоваров.Добавить("Молоко Простоквашино 3.2% 950мл");
МассивТоваров.Добавить("Молоко Домик в деревне 2.5% 1л");
МассивТоваров.Добавить("Кефир Простоквашино 1%");
МассивТоваров.Добавить("Сметана Простоквашино 20% 315г");
МассивТоваров.Добавить("Творог Простоквашино 5% 220г");
МассивТоваров.Добавить("Масло сливочное Крестьянское 72.5%");
МассивТоваров.Добавить("Йогурт Активиа клубника 150г");
МассивТоваров.Добавить("Молоко Веселый молочник 3.2%");
// Заведомо "грязный" запрос с опечаткой
Запрос = "малако прастоквашино";
Результаты = НайтиПохожиеСтроки(Запрос, МассивТоваров, 3);
// Выводим результат
Сообщить("Запрос: " + Запрос);
Сообщить("—————————————————————");
Для Каждого Элемент Из Результаты Цикл
Сообщить(Строка(Элемент.text) + " ("+Строка(Элемент.score)+"%)" );
КонецЦикла;
КонецПроцедуры
&НаСервере
Функция НайтиПохожиеСтроки(Запрос, МассивСтрок, Количество = 5)
Каталог = КаталогВременныхФайлов();
Вход =
Каталог + "request_" +
Строка(Новый УникальныйИдентификатор()) +
".json";
Выход =
Каталог + "response_" +
Строка(Новый УникальныйИдентификатор()) +
".json";
// Формируем JSON
Данные = Новый Структура;
Данные.Вставить("query", Запрос);
Данные.Вставить("limit", Количество);
Данные.Вставить("items", МассивСтрок);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ОткрытьФайл(Вход);
ЗаписатьJSON(ЗаписьJSON, Данные);
ЗаписьJSON.Закрыть();
// Запускаем EXE
Команда =
"""" +
""+КаталогПрограммы()+"fuzzlink.exe" +
""" """ +
Вход +
""" """ +
Выход +
"""";
Код = 0;
ЗапуститьПриложение(
Команда,
,
Истина,
Код
);
Если не (Код = 0 или Код = "0") Тогда
ВызватьИсключение
"Ошибка запуска приложения умного поиска!";
КонецЕсли;
ФайлОтвета = Новый Файл(Выход);
Если НЕ ФайлОтвета.Существует() Тогда
ВызватьИсключение
"Файл ответа умного поиска не найден";
КонецЕсли;
// Читаем результат
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьФайл(Выход);
Ответ =
ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Очистка
УдалитьФайлы(Вход);
УдалитьФайлы(Выход);
Если НЕ Ответ.success Тогда
ВызватьИсключение Ответ.error;
КонецЕсли;
Возврат Ответ.results;
КонецФункции
О программе fuzzlink
fuzzlink - это написанная мной на языке python маленькая консольная программа и скомпилированная в .exe файл (не требует установки python или других зависимостей) в которой используется бесплатная библиотека RapidFuzz;
Код программы опубликован в github.
Скомпилированный .exe можете скачать там-же в папке /dist, или же в макете обработки прикрепленной к этой статье.
Найденные мной решения не совсем удовлетворили требования и оказались достаточно древними. Буду рад, если кому-либо статья окажется полезной.
Проверено на следующих конфигурациях и релизах:
- Бухгалтерия предприятия, редакция 3.0, релизы 3.0.201.16
Вступайте в нашу телеграмм-группу Инфостарт