Перейти к содержанию
Публикация AiManual

Почему fuzzy matching не спасает при сопоставлении коротких идентификаторов в даталейке

Разбираем, почему Damerau-Levenshtein, Jaro-Winkler и q-gram Jaccard ошибаются на коротких буквенно-цифровых кодах и создают риск false merge. Показываем практи

Коротко

Что будет в материале

  1. 01

    Короткий ответ: почему fuzzy matching не работает на коротких кодах

  2. 02

    Почему короткие идентификаторы особенно сложны для сопоставления

  3. 03

    Damerau-Levenshtein для коротких кодов: что именно он не видит

  4. 04

    Jaro-Winkler и q-gram Jaccard: почему другие метрики не дают безопасного порога

Короткий ответ: почему fuzzy matching не работает на коротких кодах

Fuzzy matching сравнивает форму строк. Короткий буквенно-цифровой код описывает сущность только косвенно, поэтому одна замена символа, перестановка или общий префикс могут означать обычную опечатку либо другой действующий артикул.

Пара A1B2 и A1B3 отличается одной заменой. Для Damerau-Levenshtein это расстояние 1. Но каталог может трактовать последний символ как номер ревизии, цвет, регион или отдельную упаковку. В другом источнике такая же замена появится из-за ошибки ввода. Алгоритм видит одинаковую операцию и не различает бизнес-сценарии.

Поэтому Damerau-Levenshtein, Jaro-Winkler и q-gram Jaccard подходят для поиска и ранжирования кандидатов, но не дают универсального безопасного порога для автоматического merge. Решение должно опираться на внешний справочник или master data, атрибуты записи, детерминированные правила, ручную верификацию и датированную историю mapping. Fuzzy matching здесь навигатор по кандидатам, а не доказательство идентичности.

СитуацияЧто происходитРиск
Опечатка не распознанаОдин объект остаётся под несколькими ключамиFalse negative, или false split, потеря полноты и раздробленная статистика
Разные коды слитыФакты двух объектов попадают под один canonical_idFalse positive, или false merge, смешение продаж, цен, остатков и событий
Несколько близких кандидатовМетрика не может выбрать объект по строкеAmbiguous match, запись должна попасть на ревью
Код отсутствует в каталогеДля строки нет подтверждённой сущностиUnresolved, автоматическое присвоение похожего ключа создаёт ложное знание

Одинаковая похожесть, разные бизнес-смыслы

Представим каталог с кодами AB12 и AB13. Это могут быть две ревизии одного изделия, два цвета или полностью независимые позиции. Пусть в выгрузке встречается AB12, а в другой строке записано AB1Z. Строковая метрика оценит близость, однако без описания, производителя и даты действия неизвестно, что произошло: оператор ошибся с цифрой или источник передал новый код.

Другой пример связан с перестановкой соседних символов. Для пары A1B2 и AB12 Damerau-Levenshtein может зафиксировать одну транспозицию. Такая ошибка типична для ручного ввода. Тот же результат получится у настоящего кода, который случайно использует другую последовательность символов. Формула не хранит сведения о допустимых артикулах и не знает, какая позиция в коде значима.

Главный риск: не пропущенная опечатка, а ложное слияние

False split неприятен: одна сущность продолжает жить в нескольких строках справочника, отчёт показывает неполный объём. False merge опаснее для многих даталейков: продажи, остатки, цены, возвраты или события двух объектов получают общий канонический ключ. Ошибка может незаметно попасть в несколько downstream-витрин.

Количество автоматически обработанных строк не заменяет оценку качества. Нужно отдельно считать false merge, false split, unmatched и ambiguous match. Для критичных идентификаторов лучше сохранить значение со статусом unresolved, чем присвоить ему похожий ключ без подтверждения.

Почему короткие идентификаторы особенно сложны для сопоставления

Короткая строка содержит мало символов, и каждый из них получает большой вес. В коде из четырёх знаков одна замена затрагивает 25% символов. В коде из восьми знаков та же операция затрагивает 12,5%. Процент не определяет бизнес-риск напрямую, но показывает, почему длина сильно влияет на числовой score.

Один символ может менять сущность, а не исправлять опечатку

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

Условные коды PRD-01 и PRD-02 могут быть соседними версиями, а PRD-01 и PRD-O1 могут содержать визуальную подмену цифры буквой. Если справочник допускает только цифровое значение в последнем блоке, это правило даст больше информации, чем расстояние строк. Если такая подмена разрешена конкретным источником, правило должно учитывать источник.

Префикс и формат не доказывают идентичность

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

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

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

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

В названии насос высокого давления перестановка букв обычно выглядит как шум. В коде NP-100 и NP-101 один символ может разделять две позиции каталога. Embeddings и LLM тоже не получают права угадывать canonical_id только по визуальной похожести: без проверяемого справочника модель способна уверенно выбрать неверную сущность.

Damerau-Levenshtein для коротких кодов: что именно он не видит

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

Расстояние 1: опечатка или другой допустимый код

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

Правило «расстояние 1 означает опечатку» работает только внутри узкого домена, где размечены допустимые варианты и доказано отсутствие соседних кодов с таким расстоянием. Универсального условия для всех справочников здесь нет. Порог следует калибровать на контрольной выборке с парами true match, true non-match и ambiguous case, причём false merge и false split нужно считать отдельно.

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

Нормализация может как помочь, так и стереть сигнал

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

Рискованные правила требуют отдельного контроля:

  • замена O на 0 и I на 1 может исправить OCR-шум, но способна уничтожить различие между двумя реальными кодами;
  • удаление ведущих нулей меняет значение, если 00127 и 127 считаются разными ключами;
  • обрезка суффикса стирает сведения о версии, регионе или упаковке;
  • удаление дефисов допустимо только там, где каталог считает AB-12 и AB12 одной формой.

Raw-значение нужно сохранять рядом с нормализованным. Для каждого преобразования полезны версия правила, признак применённой операции и источник записи. Практический разбор границ Levenshtein для шумного текста есть в материале о spell-check и шуме в enterprise RAG, но для идентификаторов итог зависит от каталога сильнее, чем от самой метрики.

Jaro-Winkler и q-gram Jaccard: почему другие метрики не дают безопасного порога

Смена формулы меняет способ измерения похожести, но не добавляет системе знания о сущности. Jaro-Winkler может завысить оценку за общий префикс, q-gram Jaccard зависит от небольшого набора фрагментов, а Damerau-Levenshtein одинаково относится к замене значимого и незначимого символа.

Jaro-Winkler для идентификаторов: бонус за общий префикс

Jaro-Winkler учитывает совпадения символов и добавляет бонус за общий префикс в начале строки. Для имён и коротких текстовых значений это иногда помогает поднять в выдаче варианты с одинаковым началом.

В кодах префикс часто шаблонный. Значения SKU-EU-104 и SKU-EU-907 могут принадлежать разным позициям, хотя первые блоки совпадают. Если решающий признак находится в последнем блоке, префиксный бонус поднимает в рейтинге сразу несколько ложных кандидатов. Jaro-Winkler удобно применять для сортировки, но его высокий score не следует превращать в подтверждённый match.

q-gram Jaccard на коротких строках: слишком мало признаков

q-gram Jaccard разбивает строку на фрагменты длиной q и сравнивает пересечение с объединением наборов. Для AB12 при q=2 получаются биграммы AB, B1, 12. У AB13 набор будет AB, B1, 13. Пересечение содержит два фрагмента, объединение четыре, поэтому Jaccard равен 2/4 = 0,5, если используются множества без padding.

При q=3 картина меняется: для первой строки получаются AB1 и B12, для второй, AB1 и B13. Пересечение равно одному фрагменту, объединение содержит три, результат равен 1/3. Padding по краям, повторяющиеся q-граммы и выбор длины фрагмента изменят результат ещё сильнее.

Короткая строка порождает мало признаков. Одна замена может изменить значительную долю набора, а результат будет чувствителен к длине кода и параметру q. Поэтому q-gram Jaccard помогает искать похожие варианты внутри ограниченного блока, но не доказывает их тождество.

Почему нельзя выбрать одну метрику и объявить её источником истины

МетодЧто измеряетЧто может переоценитьБезопасная роль
Damerau-LevenshteinМинимум вставок, удалений, замен и транспозицийЛюбая операция получает числовую цену без учёта роли позицииПоиск опечаток и первичное ранжирование
Jaro-WinklerСовпадения, порядок и общий префиксКоды с одинаковым шаблонным началомСортировка кандидатов внутри одного блока
q-gram JaccardПересечение наборов фрагментовСлучайные совпадения при малом числе q-граммФильтрация и анализ локальных вариантов

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

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

Без внешнего каталога строка не знает, что именно она обозначает

Идентичность короткого кода часто хранится в reference data или master data. Каталог связывает canonical_id с каноническим значением, допустимыми алиасами, источниками, атрибутами и периодом действия. Такая связь даёт системе сведения, которых нет в строке.

Какие признаки нужны кроме самой строки

Набор признаков зависит от домена, но на практике часто проверяют:

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

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

Каталог как арбитр конфликтующих кандидатов

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

Если каталог связывает AB12 и AB13 с разными объектами, близость строк не может разрешить конфликт. Если после фильтрации остаются две допустимые сущности, запись получает статус ambiguous. Если подтверждающий кандидат отсутствует, сохраняется unresolved. Канонический ключ в обоих случаях не публикуется как окончательный.

Что делать, если каталог неполный или устарел

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

Система должна сохранить raw-значение, источник и контекст, создать задачу на пополнение каталога и оставить запись нерешённой. После появления новой сущности можно повторно обработать только затронутые значения, если mapping хранит версии правил и историю решений.

Безопасный pipeline сопоставления в даталейке

Надёжный pipeline разделяет техническое преобразование строки и бизнес-решение о принадлежности к сущности. Поток может выглядеть так: ingest, raw-слой, нормализация, exact match, генерация кандидатов, контекстная проверка, ревью, публикация и аудит.

Шаг 1. Сохранить raw-значение и источник

Входной слой должен хранить значение без изменений. Минимальный набор полей:

  • raw_value, строка как её передал источник;
  • source_system, система или поток загрузки;
  • record_id, идентификатор исходной записи;
  • ingested_at, время поступления;
  • processing_version, версия кода или схемы обработки.

Нормализованный код и канонический ключ хранятся отдельными полями. Raw-слой нельзя затирать результатом матчинга: иначе после изменения правила будет трудно понять, что пришло из источника и на каком шаге возникла ошибка.

Шаг 2. Выполнить детерминированную нормализацию

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

Нормализация меняет представление, но не присваивает canonical_id. Например, удаление пробела по краям и перевод латинских букв в верхний регистр могут подготовить строку к exact match. Замена O на 0 уже содержит гипотезу и должна идти отдельным правилом с записью основания.

Полезно хранить три значения: raw_value, normalized_value и normalization_rule_version. Это позволяет повторить расчёт и откатить спорное преобразование.

Шаг 3. Сначала exact match, затем поиск кандидатов

Первым шагом после нормализации выполняется точный поиск по каноническому коду и утверждённым алиасам. Exact match уменьшает число неоднозначных случаев и не расходует fuzzy-поиск на значения, для которых ответ уже известен.

Для unmatched-значений задаются блоки кандидатов. Блок может учитывать длину, шаблон, источник, производителя, категорию или регион. Fuzzy-метрика запускается внутри такого блока, а не по всему каталогу.

Каскадная архитектура для enterprise-документов, где точные правила, словари и embeddings занимают разные места, разобрана в материале о замене RAG более дешёвыми NLP-методами. Для коротких кодов принцип тот же: дорогой или вероятностный этап должен получать уже ограниченный набор кандидатов.

Шаг 4. Разделить автоматическое подтверждение и очередь ревью

Технический score и бизнес-вердикт должны храниться раздельно. Удобна модель из трёх зон:

  1. Confirmed. Сопоставление подтверждено exact match, утверждённым алиасом или набором независимых правил.
  2. Review. Есть один или несколько кандидатов, но требуется человек или дополнительный атрибут.
  3. Unresolved. Подходящий кандидат не найден, каталог неполон или признаки противоречат друг другу.

Для каждой записи сохраняются score, список кандидатов, использованные признаки, версия правила, решение, причина и автор решения. В поле причины лучше писать структурированный код, например exact_alias, conflicting_pack_size или catalog_missing, а пояснение хранить отдельно.

Шаг 5. Публиковать канонический ключ только после контроля

Таблица соответствий должна быть отдельным управляемым слоем. В ней хранятся raw-значение, источник, canonical_id, статус, период действия, основание и аудит. Фактические витрины ссылаются на версию approved mapping.

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

Как оценить цену ручной проверки и не потерять редкие совпадения

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

Какие ошибки нужно разделять в отчёте

КатегорияСмыслПоследствие
False mergeДве разные сущности получили один canonical_idСмешение фактов и искажение агрегатов
False splitОдна сущность осталась под разными ключамиНеполные отчёты и рост дублей
UnmatchedКандидат не найденЗадержка публикации или неполная витрина
AmbiguousПодходящих кандидатов несколькоНужна ручная проверка или новый атрибут

Для разных категорий нужны разные меры. False merge проверяют через независимые атрибуты и контрольные выборки. False split ищут по повторяющимся описаниям, связям и группам источников. Unmatched помогает находить пробелы каталога, а ambiguous показывает, где текущих правил недостаточно.

Минимальный набор KPI для очереди ревью

На потоке нужно измерять:

  • число новых уникальных raw-значений и число записей, которые они затрагивают;
  • размер очереди и среднее число кандидатов на один кейс;
  • долю confirmed, rejected, ambiguous и unresolved;
  • acceptance rate и rejection rate после проверки;
  • среднее и медианное время обработки;
  • backlog, возраст самого старого кейса и число повторных проверок;
  • precision и recall на независимой размеченной выборке;
  • частоту false merge и false split по источникам, типам кодов и версиям правил.

Precision для принятых связей можно считать как долю подтверждённых true match среди всех принятых match. Recall показывает, какую долю всех известных true match система нашла. Эти показатели нужно дополнять стоимостью ошибок: false merge может быть существенно дороже задержки для одного unresolved-кода, но конкретное соотношение задаётся бизнесом.

Повторяющиеся значения лучше группировать в один кейс, если их raw-форма, источник и контекст совпадают. Это снижает число одинаковых решений, не меняя критерии auto-merge.

Почему редкие случаи нельзя просто отфильтровать

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

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

Дедупликация и entity resolution решают связанные, но разные задачи. Подходы к поиску повторяющихся объектов в больших датасетах, включая MinHash и LSH, разобраны в материале о дедупликации данных для LLM. Наличие похожего текста ещё не означает, что две записи можно объединить в один бизнес-объект.

Как сокращать ревью без расширения опасного auto-merge

Снизить нагрузку можно через качество процесса:

  • объединять одинаковые кейсы по raw-значению, источнику и контексту;
  • сначала проверять записи с высокой ценой ошибки и большим downstream-охватом;
  • группировать похожие проблемные значения для одного решения оператора;
  • повторно использовать утверждённые алиасы после проверки их области действия;
  • пополнять каталог новыми каноническими значениями и правилами источников;
  • измерять false merge на контрольной выборке перед любым изменением порога.

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

Effective dating: почему метку сопоставления нужно датировать

Связь между raw-значением и canonical_id может меняться со временем. Артикул переименовывают, позицию закрывают, локальный код связывают с другой сущностью, а справочник получает новую версию. Простая постоянная замена строки теряет эту историю.

Статусы решения: confirmed, rejected, unresolved

confirmed означает, что связь прошла заданные проверки. rejected фиксирует отклонённого кандидата, который нельзя использовать для этого значения и контекста. unresolved сообщает, что решение пока отсутствует.

Для старых решений полезны статусы stale и superseded. Первый показывает, что связь требует проверки после изменения каталога. Второй указывает, что её заменило новое решение. Статусы должны быть различимы: отклонённый кандидат и ещё не проверенное значение требуют разных действий.

Период действия важнее последнего найденного совпадения

Mapping может содержать поля valid_from и valid_to. При обработке исторической записи система выбирает связь, действовавшую в её бизнес-дату, если такие правила предусмотрены доменом.

Пример: код поставщика X-17 был связан с одной позицией в январе, а после смены ассортимента получил новое значение в июле. Применение последней версии каталога ко всей истории перенесёт январские факты в новую сущность. Датированный mapping сохраняет обе связи и даёт возможность явно пересчитать затронутый период.

Вместе с периодом нужно хранить catalog_version. Изменение справочника не должно молча переписывать прошлые решения.

Аудит: кто, когда и на основании чего подтвердил связь

Запись аудита должна отвечать на несколько вопросов: какой кандидат нашёлся, какие правила сработали, какие атрибуты совпали или конфликтовали, какой score получил вариант, кто подтвердил решение и какая версия каталога действовала.

Минимальная схема mapping может выглядеть так:

raw_value
normalized_value
canonical_id
source_system
decision_status
decision_source
valid_from
valid_to
catalog_version
rule_version
reviewer_id
created_at
updated_at

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

Где могут помочь LLM и автоматические классификаторы, а где им нельзя доверять

LLM полезна рядом с решением, если её вывод можно проверить. Модель может обработать контекст, объяснить различия между кандидатами и помочь оператору быстрее принять решение. Она не должна единолично назначать canonical_id для короткого кода при отсутствии подтверждения в каталоге.

Что можно поручить модели

  • извлекать бренд, размер, упаковку, регион и версию из названия или описания;
  • ранжировать кандидатов по совокупности текстовых и структурных признаков;
  • формировать краткое объяснение, почему два кода отличаются;
  • обнаруживать конфликтующие атрибуты и подозрительные пары;
  • кластеризовать повторяющиеся unresolved-значения;
  • подготавливать оператору карточку ревью с raw-значением, кандидатами и основаниями.

Для узкой задачи извлечения признаков локальная модель иногда удобнее универсального чат-LLM. Критерии выбора компактной модели и риски изменения смысла при очистке текста разобраны в материале о локальной модели для очистки диктовки. Для матчинга принцип сохраняется: модель помогает подготовить признаки, а не отменяет проверку ключа.

Что должно остаться за кодом и каталогом

Детерминированная логика должна контролировать:

  • нормализацию и валидацию формата;
  • существование canonical_id в выбранной версии каталога;
  • уникальность связи для конкретного источника и периода;
  • совместимость атрибутов и временные ограничения;
  • статус публикации в downstream-витрины;
  • аудит, версию правил и возможность отката.

LLM может предложить кандидата или текст объяснения. Код проверяет формальные условия, каталог хранит допустимые связи, а человек в контуре принимает неоднозначное решение. Такой раздел ответственности сохраняет воспроизводимость и упрощает разбор ошибок.

Практический план: как встроить сопоставление коротких кодов в даталейк

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

Начать с небольшого набора источников и типов кодов

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

Для каждого сегмента измеряйте долю exact match, число кандидатов, размер review-очереди, долю unresolved и результаты ручных решений. Общая цифра по всему даталейку может скрыть источник, который создаёт почти все конфликты.

Собрать контрольную выборку до настройки порогов

Контрольная выборка должна содержать true match, true non-match и ambiguous case. Пары проверяются человеком по каталогу и доступным атрибутам. В выборке нужны частые, редкие, короткие, повреждённые и пограничные значения.

На этой выборке сравниваются precision и recall, но итоговое решение принимается с учётом стоимости false merge и false split. Порог, который выглядит удобным по одной метрике, может плохо работать для отдельных источников. Его нужно хранить вместе с версией правил и составом выборки.

Встроить mapping в процесс эксплуатации

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

Полезный эксплуатационный минимум:

  1. ежедневно собирать новые raw-значения и конфликты атрибутов;
  2. показывать оператору кандидатов, признаки, score и историю решений;
  3. публиковать только approved mapping с версией;
  4. периодически пересматривать решения со статусом stale;
  5. сохранять возможность пересчёта после обновления каталога.

Сопоставление становится управляемым слоем данных, а не одноразовым скриптом. Это особенно важно, когда один и тот же raw-код приходит из нескольких систем или его смысл меняется с датой.

Итог: fuzzy matching - это навигатор по кандидатам, а не доказательство идентичности

Fuzzy matching уместен для генерации кандидатов, поиска потенциальных опечаток, обнаружения проблемных значений и подготовки очереди ревью. Damerau-Levenshtein, Jaro-Winkler и q-gram Jaccard помогают измерить разные свойства строки, однако ни одна метрика не видит сам объект каталога.

Когда fuzzy matching уместен

  • для поиска близких вариантов внутри заранее ограниченного блока;
  • для ранжирования кандидатов после exact match и проверки формата;
  • для анализа качества входных данных;
  • для поиска повторяющихся опечаток и подготовки алиасов;
  • для подсказки оператору при наличии каталога и контекстных признаков.

Автоматическое слияние допустимо, когда есть независимое подтверждающее условие: exact match по утверждённому алиасу, уникальная комбинация атрибутов или формальное правило источника. Один score таким условием не считается.

Когда лучше остановиться на ручной проверке

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

Безопасная архитектура хранит raw-значение, применённую нормализацию, список кандидатов, статус решения, период действия, версию каталога и аудит. Fuzzy matching сокращает путь до проверки, но финальное качество определяется тем, какой mapping опубликован и можно ли восстановить его историю.

Подписаться на канал