Как работает поиск? (объясняем "на пальцах")

Главная идея: Сервис не ищет точное совпадение слов. Он ищет СМЫСЛ и ПОХОЖЕСТЬ. Поэтому "блот" находит "болт", а "цинк" находит "оцинкованный".

Пошагово: что происходит, когда вы отправляете запрос

  1. Вы отправляете запрос в 1С
    Например, оператор вводит "блот м16 цынк" (с двумя опечатками).
  2. 1С вызывает сервис
    POST /find {"items":[{"name":"блот м16 цынк"}]}
  3. Сервис исправляет опечатки (если включено)
    "блот" → "болт" (расстояние Левенштейна)
    "цынк" → "цинк"
  4. Сервис приводит слова к нормальной форме
    "болты", "болтом", "болтов" → "болт". Это называется стемминг.
  5. Применяются синонимы
    Если в конфиге есть синоним "цинк" → "оцинкованный", сервис ищет оба варианта.
  6. Поиск в индексе
    Сервис быстро находит все товары, которые содержат "болт", "м16", "оцинкованный".
  7. Ранжирование (сортировка по релевантности)
    Сервис считает для каждого товара score — число от 0 до 1, где 1 — идеальное совпадение. Товары, совпавшие с запросом по большему числу слов, получают более высокий score и поднимаются выше в списке. Это настраивается параметром search.weights.coverage_boost_per_token.
  8. Фильтрация по порогам
    Сервис находит максимальный score среди кандидатов и отбрасывает товары, у которых score ниже max_score × auto_match_threshold (по умолчанию 0.85). Также учитывается абсолютный минимум absolute_min_score. Порог работает одинаково для BM25, эмбеддинг и гибридных стратегий.
  9. Ответ сервиса
    Сервис возвращает JSON с найденными товарами, их score и способом совпадения.
  10. 1С показывает результат оператору
    "Возможно, вы имели в виду Болт М16х60 оцинкованный?"

Что такое score и как его понимать

Score — это число от 0 до 1, которое показывает, насколько найденный товар похож на ваш запрос.

Значение scoreЧто значитЧто делать в 1С
1.0Идеальное совпадение (тот же GUID или штрихкод)Автоматически использовать — это точно тот же товар
0.90 - 0.99Почти точно тот же товар (отличается только незначительно)Показать оператору: "Скорее всего, это он"
0.75 - 0.89Похоже, но не увереныПоказать список вариантов — пусть оператор выберет
< 0.75Слабое совпадениеНе показывать — создать новый товар
Совет по настройке порога:
  • Если сервис часто предлагает неверные товары → увеличьте auto_match_threshold до 0.90-0.92
  • Если сервис часто ничего не находит (хотя товар есть) → уменьшите auto_match_threshold до 0.75-0.80
  • Начните с 0.85 — это баланс для большинства баз

Три уровня поиска (от простого к сложному)

  1. Точные совпадения (мгновенно, 1-2 мс)
    Если вы ищете по id, barcode, code или art — сервис сначала проверяет их. Нашел → сразу возвращает результат. Дальше даже не ищет.
  2. N-gram поиск (для коротких запросов, 2-5 мс)
    Если вы ищете "перф", а в базе "Перфоратор". Обычный поиск не находит, потому что "перф" слишком короткий. N-gram разбивает "Перфоратор" на части: "Пер", "Перф", "Перфо", "Перфор" — и находит по "Перф". Настраивается в search.edge_ngram.
  3. Нечеткий поиск (fuzzy, 3-10 мс)
    Если точного совпадения нет, сервис ищет с учетом опечаток, разных форм слов и синонимов. Использует расстояние Дамерау-Левенштейна — алгоритм, который считает, сколько операций (замена, вставка, удаление или перестановка соседних символов) нужно, чтобы слово совпало. "блот" → "болт" (перестановка соседних букв) — найдет. "блооот" → "болт" (2 операции) — тоже найдет, если разрешено.

Как синонимы улучшают поиск

Синонимы — это слова, которые считаются одинаковыми при поиске. Например:

  • "цинк" = "оцинкованный" = "zn" = "zinc"
  • "нерж" = "нержавеющий" = "stainless" = "a2"
# Добавляем синонимы через API
        curl -X POST http://localhost:8080/synonyms \
          -H "Content-Type: application/json" \
          -d '{"items":[
            {"word":"цинк","expansions":["оцинкованный","zn","zinc"]},
            {"word":"нерж","expansions":["нержавеющий","stainless","a2"]}
          ]}'
# Тот же запрос через CLI
sku-cli synonyms add --word "цинк" --expansions "оцинкованный,zn,zinc"

После добавления синонимов запрос "болт м16 цинк" найдет "Болт М16х60 оцинкованный" с высоким score.

Где брать синонимы?
  • Сервис сам анализирует ваши действия и предлагает синонимы через GET /admin/learn (PRO only)
  • Вы можете добавлять вручную через API или CLI
  • Синонимы применяются мгновенно, перезапуск сервиса не нужен

Пример из реальной жизни

Запрос оператора: "блот м16 цынк" (с двумя опечатками)

Что делает сервис:

  1. Исправляет опечатки: "блот" → "болт", "цынк" → "цинк"
  2. Применяет синонимы: "цинк" → "оцинкованный"
  3. Ищет в индексе: товары, содержащие "болт", "м16", "оцинкованный"
  4. Находит "Болт М16х60 оцинкованный"
  5. Считает score: 0.94 (очень похоже)
  6. Возвращает результат
{
          "matches": [{
            "name_out": "Болт М16х60 оцинкованный ГОСТ 7798-70",
            "score": 0.94,
            "matched_by": "fuzzy_text"
          }]
        }

Оператор в 1С видит: "Возможно, вы имели в виду Болт М16х60 оцинкованный? Нажмите 'Да' чтобы использовать существующий товар."

Поля type и ref: фильтр по типу и прямая ссылка на объект 1С

Помимо id, сервис поддерживает два поля, которые упрощают интеграцию с 1С:

  • ref — сериализованная ссылка 1С (например, результат ЗначениеВСтрокуВнутр()). Сервис хранит ее как есть и возвращает в ответе, а поиск по ней — точный.
  • type — тип объекта (например, Справочник.Номенклатура). Позволяет ограничить поиск одним классом объектов или комбинировать с art, barcode, code.

Оба поля участвуют в exact-поиске и работают даже с пустым name.

# Поиск по ref
    curl -X POST http://localhost:8080/find \
      -H "Content-Type: application/json" \
      -d '{"items":[{"name":"","ref":"e1cib/data/Справочник.Номенклатура?ref=a1b2c3d4e5f6..."}]}'
# Тот же запрос через CLI
sku-cli search --ref "e1cib/data/Справочник.Номенклатура?ref=a1b2c3d4e5f6..."
# Поиск с фильтром по type
    curl -X POST http://localhost:8080/find \
      -H "Content-Type: application/json" \
      -d '{"items":[{"name":"болт","type":"Справочник.Номенклатура"}]}'
# Тот же запрос через CLI
sku-cli search "болт" --type "Справочник.Номенклатура"

Транслитерация и неправильная раскладка

Если в конфиге включено search.transliteration_enabled = true, сервис автоматически понимает запросы, набранные не в той раскладке или латиницей.

# «Домик в деревне», набрано на русской раскладке как латиница
    curl -X POST http://localhost:8080/find \
      -H "Content-Type: application/json" \
      -d '{"items":[{"name":"ljvbr d lthtdyt"}]}'

# Та же фраза латиницей
    curl -X POST http://localhost:8080/find \
      -H "Content-Type: application/json" \
      -d '{"items":[{"name":"domik v derevne"}]}'
# Тот же запрос через CLI
sku-cli search "ljvbr d lthtdyt"
sku-cli search "domik v derevne"

Сервис размножает каждый токен запроса на возможные варианты (исходный, исправленная раскладка, транслитерация) и ищет по всем сразу. Работает для кириллицы и латиницы.

Настройка. Точность распознавания контролируется параметром search.transliteration_threshold (по умолчанию 0.35). Уменьшите порог, если сервис слишком редко срабатывает на транслит; увеличьте, если появляются ложные срабатывания.
PRO: Семантический поиск (эмбеддинги)

Если включены эмбеддинги (PRO only), сервис может искать товары по смыслу, а не только по словам.

Например: "шуруповерт" найдет "дрель-шуруповерт" и "винтоверт", даже если этих слов нет в запросе. Векторы "понимают", что эти слова означают похожие инструменты.

Как настроить эмбеддинги →