Как мы перестали мучиться с сопоставлением каталогов и собрали решение за 15 минут без программистов

Excel, Python и Elasticsearch курят в сторонке

Как мы перестали мучиться с сопоставлением каталогов и собрали решение за 15 минут без программистов

У нас большая розница — десятки тысяч товаров в наличии, ещё больше под заказ. Регулярно прилетают прайс-листы от поставщиков, и каждый раз начинается головная боль: нужно понять, какие позиции из этого файла уже есть у нас в каталоге, а какие — новые. Задача вроде бы простая, но на практике это ад.

Почему? Потому что названия у всех разные. У нас товар называется «Картридж HP 26A (CF226A) черный, 3100 стр.», а у поставщика — «HP 26A Blk Toner Cartridge 3.1K». Артикулы, разумеется, внутренние и тоже не совпадают. И таких позиций — десятки тысяч.

Раньше мы это делали руками. Точнее, полуруками: выгружали оба списка в Excel, писали какие-то дикие формулы с ВПР, обрезали пробелы, и всё равно 80% времени уходило на ручную сверку глазами. Три аналитика, два дня работы, выжатый лимон в конце. И это только один прайс-лист.

Потом мы попробовали написать скрипт на Python. Наивно полагали, что FuzzyWuzzy всё решит. Решил. Первые сто записей сопоставились красиво. На втором десятке тысяч скрипт начал путать «HP 26A» с «HP 26X», потому что расстояние Левенштейна у них минимальное, а товары разные и по цене, и по ресурсу. Мы бросили этот подход после третьего исправления регулярок.

Дальше был соблазн пойти по «взрослому» пути: поднять Elasticsearch, настроить нечёткий поиск, прикрутить веса, написать микросервис. Посчитали: нужно минимум два разработчика, месяц на настройку и тесты, дальше — поддержка. Бюджет получался неприличный, а задача не стоит столько, сколько за неё просят программисты. И время. Пока бы они всё это разворачивали, нам бы уже новый прайс-лист прилетел.

Конструктор Интеграм

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

Идея: не сравнивать строки, а сравнивать токены

Вместо того чтобы сравнивать названия целиком, мы разбиваем их на отдельные слова — токены. А потом сравниваем не строки, а наборы этих токенов. Звучит примитивно, но дьявол в деталях.

Допустим, у нас есть название: «Картридж HP 26A (CF226A) черный, 3100 стр.». Токенизатор (по сути, регулярка) превращает это в набор: [картридж, hp, 26a, cf226a, черный, 3100, стр]. То же самое делаем с прайс-листом поставщика. А потом ищем пересечение множеств. Чем больше токенов совпало, тем выше вероятность, что это один и тот же товар.

Первое приближение выглядит так:

  • Берём позицию от поставщика.
  • Для каждой позиции из нашего каталога считаем, сколько токенов совпало.
  • Сортируем по убыванию совпадений.
  • Профит.

Уже на этом этапе мы получили точность около 80%, что в четыре раза лучше, чем ручная работа. Но 80% — это всё ещё 20% ошибок. На десятках тысячах позиций это сотни неверных сопоставлений, которые потом надо разгребать вручную. Поэтому мы пошли дальше.

Что мы добавили, чтобы точность стала адекватной

Первое — вес токенов. Не все слова одинаково полезны. Слово «картридж» встречается в каждой второй позиции, оно не несёт никакой различительной информации. А вот «CF226A» — это конкретная модель, и её совпадение должно весить в сто раз больше. Мы сделали так: чем чаще токен встречается в каталоге, тем ниже его вес. Редкие токены получают высокий вес. Теперь мы суммируем не количество совпадений, а сумму весов. Это сразу отсекло кучу мусорных срабатываний.

Второе — обязательные совпадения. Даже с весами система иногда ошибалась на товарах с похожими названиями, но разными брендами. Например, «Блок питания 500W» от DeepCool и от Aerocool — набор токенов почти одинаковый, веса похожие, но товары разные. Мы ввели правило: среди совпавших токенов обязательно должен быть хотя бы один, помеченный как «Бренд» или «Товар». Разметили токены (это можно сделать с помощью того же ChatGPT — скормить ему список уникальных слов и попросить разложить по категориям «бренд», «категория», «признак»). После этого точность выросла ещё.

Третье — итеративность. Мы не пытаемся сопоставить всё сразу одним запросом. Мы берём 10 000 записей за раз, смотрим результат, корректируем правила. Это не месячный проект с ТЗ на 100 страниц, а живой процесс, который занимает 15 минут на итерацию.

Что по железу и производительности

Я знаю, о чём вы сейчас думаете: «Окей, но на 10 000 записей это работает, а что будет на миллионах? Не умрёт ли это всё под нагрузкой?»

У меня были ровно те же опасения. Потому что когда в каталоге 200 000 позиций, а у поставщика ещё 100 000, количество комбинаций для сравнения становится астрономическим. Но оказалось, что архитектура это вывозит. Не буду вдаваться в детали (желающие могут почитать про IDEAV и партицирование — есть отличная статья на Хабре с тестами), но факт такой: на стенде с 16 ядрами и 32 ГБ RAM база в 4.5 ТБ (это 32 миллиарда записей) обрабатывает поиск по уникальному значению за 0.5-0.7 секунды. Сложный запрос с джойнами — за 1.2 секунды. И главное — скорость не деградирует с ростом данных благодаря партицированию.

Это значит, что решение не «игрушечное». Оно работает на объёмах, которые 99% компаний никогда не увидят.

Почему я об этом пишу

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

То, что мы сделали — это не «волшебная таблетка» и не замена полноценному MDM-решению для enterprise-компаний. Но это способ решить конкретную задачу быстро, без бюджета на разработку и с приемлемой точностью. Сделал один аналитик за время, пока программисты бы ещё только писали ТЗ.

И да — мы использовали для этого low-code платформу, потому что писать код для такой задачи в 2026 году — это как копать траншею лопатой при наличии экскаватора. Технологии уже позволяют делать такие вещи «конструктором», и это не стыдно. Стыдно платить сотни тысяч за разработку того, что собирается за 15 минут.

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

P.S. Я намеренно не называю компанию, в которой работаю, и не даю ссылок на инструменты — это не рекламный пост. Просто хочу, чтобы люди, которые прямо сейчас корпят над Excel с ВПР'ами, знали: есть способ проще. Если будут вопросы по методике или инструментарию — пишите в комментарии, отвечу.

Начать дискуссию