Возьмём три фразы, которые покупатель действительно может ввести в строку поиска: «кроссовки nike air max 90 белые 42», «кросовки найк аир макс» и «беговые кроссовки женские лёгкие до 8000». Первая фраза почти точная, вторая написана с ошибками и в транслитерации, третья состоит из намерения, а не из названия: тип, пол, свойство и ограничение по цене. Любое сравнение поисковых движков, которое не проходит через такие запросы, остаётся сравнением красивых страниц документации.

Вопрос «Algolia или Typesense» часто задают как вопрос о цене и мощности сервера. Но покупателю всё равно, где живёт индекс. Ему важно, что товар нашёлся в первых строках, что фильтры не превратили выдачу в пустоту и что слово «кед» не привело к разделу с носками. Поэтому ниже мы смотрим на замену глазами человека у витрины, а ресурсы VPS подключаем там, где они начинают влиять на результат.

Небольшой каталог для честного эксперимента

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

Учебный каталог из двенадцати позиций
ТоварБрендКатегорияПолЦена, ₽Особенность
Nike Air Max 90 белыеNikeКроссовкиунисекс12 900размеры 40–45
Nike Air Max 90 чёрныеNikeКроссовкиунисекс12 900размеры 38–44
Nike Air Zoom PegasusNikeБеговые кроссовкиженские9 500лёгкие
Asics Gel LyteAsicsБеговые кроссовкиженские7 800лёгкие
Asics Gel NimbusAsicsБеговые кроссовкимужские14 200амортизация
Puma Suede ClassicPumaКедыунисекс7 200замша
Converse Chuck 70ConverseКедыунисекс8 400высокие
Adidas RunfalconAdidasБеговые кроссовкиженские5 900лёгкие
Adidas SambaAdidasКроссовкиунисекс10 500кожа
Носки спортивные Nike, 3 парыNikeНоскиунисекс1 600хлопок
Шнурки для кроссовок белыеNo nameАксессуарыунисекс300длина 120 см
Чистящий набор для кроссовокSneaker CareАксессуарыунисекс1 900щётка и спрей

В этом наборе специально есть ловушки. Носки с названием бренда конкурируют с кроссовками по слову «Nike». Шнурки и чистящий набор содержат слово «кроссовки», хотя покупатель, ищущий кроссовки, их не ждёт. Беговые кроссовки лежат в отдельной категории, а слово «лёгкие» живёт в характеристике, а не в названии. Для проверки этого хватит и двенадцати строк, а на реальном каталоге те же ловушки лишь размножатся.

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

Первая фраза: точный товар не должен потеряться

Запрос «кроссовки nike air max 90 белые 42» кажется самым лёгким, но на нём видно, как система читает несколько слов сразу. Правильный ответ один: белые Air Max 90. Чёрная пара шла бы вторым результатом, а носки, шнурки и чистящий набор не должны попадать выше этих двух позиций.

Что именно наблюдать:

  • какая позиция стоит первой и есть ли в первой тройке товар не того цвета;
  • как система поступает с «42»: размер хранится в отдельном поле, и число может не совпасть ни с чем в названии;
  • поднимаются ли носки Nike выше шнурков и аксессуаров только из-за бренда;
  • что происходит, если убрать слово «белые»: остаётся ли Air Max 90 в верхней части выдачи.

Здесь стоит помнить, что в документации Algolia релевантность описана не только как совпадение текста, но и как результат настроек ранжирования: там различаются searchable attributes, custom ranking, rules, synonyms и facets как отдельные инструменты (Algolia: Relevance overview). Практический вывод для переноса простой: порядок выдачи в вашем сегодняшнем магазине — это сумма нескольких слоёв. Часть из них вы могли настраивать давно и забыть. Если в Typesense вы повторите только список полей для поиска, вы перенесёте один слой из нескольких и получите другую выдачу, хотя данные те же.

Поэтому перед запуском нового индекса запишите, какие поля сейчас участвуют в поиске и в каком порядке, чем ранжируются товары с одинаковым текстовым совпадением (продажи, наличие, маржа, новинки) и какие ручные правила закреплены за популярными запросами. Это не список для переноса «один в один», а список вопросов, на которые новая система должна дать ответ своими средствами. Typesense мы не считаем совместимой заменой по API или по ранжированию: у неё свои параметры, и результат придётся наблюдать, а не предполагать.

Вторая фраза: опечатка и транслит как поведение, а не как функция

«кросовки найк аир макс» — запрос человека с телефона, который торопится. В нём пропущена буква, бренд написан по-русски, а модель названа по звучанию. Здесь ломается много красивых сравнений, потому что в таблице функций у обеих систем стоит галочка «терпимость к опечаткам», а в выдаче результат разный.

Разделим этот запрос на три независимые трудности:

  1. Опечатка в слове. «кросовки» против «кроссовки». Одна пропущенная буква — самый мягкий случай. Проверьте, находится ли тот же набор товаров, что и по правильному написанию.
  2. Другой алфавит. «найк» против Nike. Это уже не опечатка: пока в данных нет русского написания бренда или правила соответствия, обычная терпимость к ошибкам тут не поможет. Если вы раньше решали это через синонимы, это место обязательно нужно отдельно проверить.
  3. Название по звучанию. «аир макс» против Air Max. Такая же история, плюс пробел между словами.

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

Чего здесь не стоит делать — объявлять победителя по одному запросу. Если в вашем учебном наборе одна система вернула белые Air Max первыми, а другая поставила их третьими после носков, это наблюдение про конкретные настройки в конкретный день, а не приговор движку. Запишите, что именно отличалось, и возвращайтесь к настройкам: возможно, дело в весе полей или в том, что у вас в одном индексе есть русское название бренда, а в другом нет.

Третья фраза: намерение, фильтры и пустая выдача

«беговые кроссовки женские лёгкие до 8000» — самый интересный запрос. Покупатель сразу сформулировал и категорию, и пол, и свойство, и бюджет. Идеальный ответ в нашем учебном каталоге — Asics Gel Lyte за 7 800 и Adidas Runfalcon за 5 900. Nike Pegasus за 9 500 выше бюджета, и его появление в выдаче тоже надо оценить: допустим ли он как «почти подходящий» или это ошибка.

Тут проверяется то, чего нет в предыдущих двух фразах: что делает поиск с частью запроса, которая не является текстом товара. Слово «до» и число «8000» не встречаются в названиях. Возможны три сценария:

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

Третий вариант — это уже работа приложения, а не поискового движка, и при переезде она остаётся вашей. Если сегодня такое поведение даёт слой на стороне Algolia, его нужно найти и осознанно воспроизвести. Если же разбор запроса уже делает ваш код, то он переедет вместе с магазином и сравнение станет честнее.

Слово «лёгкие» — отдельная история. Оно живёт в характеристике товара. Включено ли это поле в поиск, зависит от настройки индекса, а не от выбора движка. Поэтому при сравнении запишите не только «нашлось или нет», но и какие поля были включены в поиск у каждой системы. Без этой записи любое различие нельзя будет объяснить.

Фасеты: как фильтры сужают выдачу и что при этом видит покупатель

После текстового запроса покупатель идёт к фильтрам слева или в выдвижной панели. Фасеты — это не украшение, а способ сказать «покажи только то, что мне подходит» и одновременно увидеть, сколько вариантов останется. Algolia называет facets отдельным инструментом настройки выдачи (Algolia: Relevance overview), и для магазина они часто важнее тонких настроек ранжирования.

Проведите на учебном каталоге такой опыт. Введите «кроссовки» и посмотрите на счётчики по брендам. Затем выберите бренд Nike и сравните, как поменялись счётчики остальных фасетов: категория, пол, диапазон цены. Покупатель ждёт, что цифры рядом с вариантами честно отражают то, что случится после клика. Если счётчик обещает «Беговые (3)», а после клика видно две позиции, это уже ошибка доверия, независимо от движка.

Что именно записать по фасетам:

  • Поведение счётчиков при выбранном фильтре. Меняются ли числа у других фасетов и совпадают ли они с реальной выдачей.
  • Множественный выбор внутри группы. Если покупатель отметил Nike и Asics, ожидание обычно такое: показать товары любого из двух брендов. Проверьте, что именно получается.
  • Диапазон цены. Граничные значения: ровно 7 800 должны попадать в «до 7 800».
  • Пустая комбинация. Что видит человек, если фильтры в сумме дали ноль. Хороший сценарий — подсказка, какой фильтр снять.
  • Отсутствующие значения. Шнурки без пола в нашем каталоге хранятся как «унисекс». Как они ведут себя при фильтре «женские»? Это вопрос данных, но он всплывёт именно в фасетах.

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

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.

АРЕНДОВАТЬ СЕРВЕР

Синонимы и торговые правила: слой, который покупатель не видит, но чувствует

Синонимы — это знание магазина о языке клиентов. «Кеды», «сникеры» и «кроссовки» для одних людей одно и то же, для других нет. «Найк» и Nike — одно слово, записанное разными буквами. Эти соответствия редко лежат в коде приложения: их добавляют в панели поиска по мере чтения отчётов о запросах без результата.

В документации Algolia синонимы и правила названы отдельными инструментами рядом с ранжированием (Algolia: Relevance overview). Для переезда отсюда следуют две практических задачи.

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

Вторая: разделение по типам. Синонимы обычно говорят «эти слова значат одно». Торговые правила говорят иное: «по этому запросу сначала покажи вот это». Первое — про язык, второе — про бизнес. Если вы сегодня закрепляете вверху выдачи сезонный товар по запросу «куртка», это не синоним, а решение маркетолога, и его перенос — вопрос договорённости внутри команды, а не техники. Мы не обещаем, что все правила переедут: нужно смотреть на возможности Typesense и на то, что вы реально используете.

Проверочные строки для нашего каталога:

Языковые и торговые правила в учебной выдаче
ЗапросЧего ждёт покупательТип слоя
найктовары Nikeсоответствие слов
сникерыкроссовки и кедысоответствие слов
кедытолько кеды, без кроссовокограничение значения
шнуркиаксессуар, а не обувькатегорийное поведение
air maxAir Max 90 выше всех прочих Nikeторговый приоритет

Заметьте строку про «кеды». Там легко получить обратное поведение: когда два слова объявлены равнозначными в обе стороны, запрос «кеды» начнёт приводить к кроссовкам, а покупатель этого не просил. Синонимы бывают односторонними и двусторонними, и ошибка направления — типичная причина странных выдач после переезда.

Настройка нового индекса и перенос аналитики — две разные работы

Есть соблазн считать, что после заливки каталога в Typesense переезд закончен. Но у поиска есть ещё память магазина: какие запросы вводили, где ничего не находили, что покупали после клика. Эта история хранится у текущего провайдера, и её судьба при переезде нужно решать отдельно.

В документации Algolia изменения релевантности предлагается оценивать через поисковую аналитику и A/B testing (Algolia: Relevance overview). Для вас это означает следующее: если именно на этих инструментах строилось принятие решений, то после переезда они не появятся сами. Мы не обещаем перенос аналитической истории, персонализации и всех правил. Что можно сделать честно:

  • выгрузить, пока есть доступ, список самых частых запросов и запросов без результатов — он станет основой набора для сравнения;
  • решить, какие показатели вы будете собирать у себя после переезда: запрос, число результатов, клик по позиции, добавление в корзину;
  • признать, что кривая «до» и кривая «после» будут построены разными способами, и сравнивать их напрямую нельзя без оговорок;
  • отдельно решить судьбу A/B-экспериментов: если вы их использовали, то в новой связке их придётся организовывать на стороне приложения.

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

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

Что даёт VPS и сколько памяти потребует индекс

У Typesense есть особенность, которая прямо определяет выбор сервера: поисковый индекс держится в памяти, а копия исходных данных лежит на диске. Объём памяти зависит от индексируемых полей и от распределения слов, а неиндексируемые поля могут храниться на диске. Опубликованные оценки по RAM служат ориентиром и не заменяют замер вашего каталога (Typesense: System requirements).

Из этого следует практический порядок действий. Не угадывайте размер сервера по числу товаров. Поднимите тестовую установку, загрузите копию каталога с реальным набором полей и посмотрите, сколько памяти занял процесс. Затем измените схему: уберите из индексации поля, по которым покупатель не ищет (например, длинное описание, если оно не нужно для поиска), и сравните потребление. Так вы увидите, что именно «весит» в вашем случае, а не вообще.

Тарифы VPS MAATRIX строятся по ступеням: Ba — 1 vCPU, 2 ГБ RAM и 40 ГБ NVMe; Uab — 2 vCPU, 4 ГБ и 80 ГБ; Heka — 4 vCPU, 8 ГБ и 160 ГБ; Maat — 8 vCPU, 16 ГБ и 240 ГБ; Djed — 16 vCPU, 32 ГБ и 320 ГБ. Диск NVMe в них нужен для хранения данных и загрузки, а оперативная память — для индекса. Эти цифры описывают ресурсы, а не обещают ёмкость: сколько товаров и запросов выдержит конкретная конфигурация, показывает только ваш замер. Для учебной копии каталога вполне может хватить небольшой ступени, но для боевого индекса выбор делайте по измеренной памяти и по нагрузке запросов, оставляя запас на рост каталога и на переиндексацию. На VPS MAATRIX доступен root-доступ, поэтому процесс установки и настройки вы контролируете сами; пошаговая установка описана в материале как установить и настроить Typesense на VPS.

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

Локация тоже часть решения. В публичном предложении перечислены UK, US, RU и FR. Для поиска магазина имеет значение сетевая близость сервера к приложению, которое отправляет запросы: лишние десятки миллисекунд на каждый ввод символа в строку подсказок покупатель заметит. Измерьте задержку из того места, где работает ваш бэкенд, а не из рабочего ноутбука.

Одна лента запросов, один каталог, два движка

Теперь соберём всё в процедуру сравнения. Её суть — убрать всё, что отличается, кроме самого движка и его настроек.

  1. Заморозьте каталог. Снимите одну выгрузку и загрузите её в обе системы. Пока идёт сравнение, не добавляйте товары в одну и не добавляйте в другую.
  2. Соберите набор запросов. Возьмите частые запросы, запросы без результатов и несколько выдуманных вами каверзных фраз, вроде трёх из начала статьи. Для магазина средних размеров вполне хватит нескольких десятков строк, лишь бы в них были все типы трудностей: точный товар, опечатка, транслит, намерение, фильтры.
  3. Зафиксируйте ожидание заранее. Для каждой фразы до запуска запишите, какие один-три товара вы считаете правильным ответом. Если записывать ожидание после просмотра выдачи, вы подсознательно подгоните его под увиденное.
  4. Запускайте оба движка одинаково. Те же запросы, тот же порядок, те же выбранные фасеты. Запишите первые пять позиций и число найденных товаров.
  5. Отмечайте причину различия. Разные поля в поиске, разные синонимы, разный вес — всё это можно исправить настройкой. Запись «Typesense хуже» без причины ничего не стоит.
  6. Повторите после правки. Если различие объяснено настройкой, поправьте её и прогоните тот же набор снова. Так вы увидите, что именно меняет каждый параметр.

Пример строки итоговой таблицы:

Фрагмент протокола сравнения (условный пример)
ЗапросОжиданиеЧто видим в AlgoliaЧто видим в TypesenseПричина различия
кросовки найк аир максAir Max 90 обе парызаполняется по фактузаполняется по фактуесть ли русское написание бренда
беговые женские лёгкие до 8000Gel Lyte, Runfalconзаполняется по фактузаполняется по фактуразбор цены в приложении или в поиске

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

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

Когда считать деньги

Экономия — естественная причина задумываться о переезде, и в ней нет ничего постыдного. Но порядок рассуждения важен. Сначала вы выясняете, находит ли новый поиск товары так, чтобы покупатель получал то, за чем пришёл. Потом оцениваете, во что обойдётся работа: сервер, время на обслуживание, мониторинг, восстановление после сбоя, перенос правил, пересборка аналитики. И только после этого сравниваете со счётом за облачный сервис.

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