Подсветка, fuzzy-поиск и автодополнение

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

fuzzy-поиск находит слова, отличающиеся от запроса на несколько правок (edit distance), прощая опечатки; highlight подсвечивает совпадения в результатах.

Подсветка совпадений (highlight)

Когда пользователь видит результаты, полезно показать, где именно совпал его запрос. ES умеет вернуть фрагменты текста с обёрнутыми совпадениями:

{
  "query": { "match": { "description": "кофемашина" } },
  "highlight": {
    "fields": { "description": {} }
  }
}

В ответе у каждого документа появится блок highlight с фрагментами, где совпавшие слова обёрнуты в теги (по умолчанию <em>...</em>). Их можно подставить в выдачу как «сниппеты».

Нечёткий поиск (fuzzy)

Люди делают опечатки: «кофемащина», «делонги». Fuzzy-поиск находит термы, отличающиеся на небольшое редакционное расстояние (расстояние Левенштейна) — число вставок, удалений и замен символов, чтобы превратить одно слово в другое.

Пара словРасстояние
кот → кит1 (одна замена)
кофе → кафе1 (одна замена)
дом → доме1 (одна вставка)
{
  "query": {
    "match": {
      "title": { "query": "кафемашина", "fuzziness": "AUTO" }
    }
  }
}

"fuzziness": "AUTO" — рекомендованный режим: ES сам подбирает допустимое расстояние в зависимости от длины слова (короткие слова — строже, длинные — мягче). Так «кафемашина» находит «кофемашина».

Автодополнение

Подсказки при наборе («коф…» → «кофемашина», «кофеварка») — отдельная задача. Наивный способ — wildcard коф* — медленный. Правильные подходы:

  • completion suggester — специальная структура (поле типа completion), оптимизированная под префиксные подсказки; очень быстрая.
  • edge n-grams — при индексации слово заранее режется на префиксы (к, ко, коф, кофе...), и поиск по префиксу превращается в обычный match по терму.

Как работает под капотом

Fuzzy-поиск не сравнивает запрос с каждым словом подряд — это было бы медленно. ES строит из запроса автомат Левенштейна и обходит словарь термов, отбирая те, что укладываются в заданное расстояние. Поэтому fuzzy дороже точного match (приходится рассматривать больше термов), но всё равно работает по индексу, а не перебором документов. Edge n-grams переносят работу на этап индексации: префиксы вычисляются один раз при загрузке, и поиск подсказок становится обычным быстрым лукапом.

Частые ошибки

  • Большая fuzziness. Допускать 3+ правки — значит находить слишком много «похожего» мусора и тормозить. AUTO почти всегда лучший выбор.
  • Автодополнение через wildcard. коф* на большом индексе медленный; используйте completion suggester или edge n-grams.
  • Highlight по огромным полям. Подсветка тяжёлых текстовых полей затратна; ограничивайте число и размер фрагментов.

Итоги

  • highlight возвращает сниппеты с обёрнутыми совпадениями для показа в выдаче.
  • Fuzzy-поиск прощает опечатки в пределах edit distance; fuzziness: AUTO — разумный режим.
  • Автодополнение делают через completion suggester или edge n-grams, а не через wildcard.
Проверьте себя
1. На чём основан нечёткий (fuzzy) поиск?
AНа синонимах
BНа редакционном расстоянии (Левенштейна): число вставок, удалений и замен символов
CНа сортировке по цене
DНа точном совпадении строки
2. Какой способ автодополнения предпочтительнее наивного wildcard коф*?
Aterm-запрос
Bcompletion suggester или edge n-grams
Cmust_not
Dsort по _id