Search by

besnovatyj / yii2-cms-search-tnt

besnovatyj

Ядро сквозного поиска на TNTSearch для Yii2 CMS: полнотекстовый индекс BM25 со стеммингом русского и поиском с опечатками, размещённый в базе проекта. Подключается к фасаду besnovatyj/yii2-cms-search, отдельного демона не требует.

Package info

github.com/besnovatyj/yii2-cms-search-tnt

Type:yii2-extension

pkg:composer/besnovatyj/yii2-cms-search-tnt

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.1.1 2026-09-07 13:42 UTC

This package is auto-updated.

Last update: 2026-09-07 13:44:10 UTC


README

Ядро для фасада besnovatyj/yii2-cms-search. Полнотекстовый индекс живёт в той же MySQL, что и контент: на сервере ставить нечего — ни демона, ни порта, ни роли ansible.

Оформлено модулем, а не пакетом: ядро включают и выключают менеджером модулей, стеммер и окно совпадений настраивают в админке (раздел настроек «Search»), а служебные таблицы заводятся миграциями при установке. Выключенный модуль означает «этого ядра в системе нет» — фасад перестанет предлагать его в настройках и останется на своём.

Что умеет

Возможность Есть Как сделано
Ранжирование BM25 да штатно в TNTSearch
Стемминг русского да Snowball (RussianStemmer); по умолчанию выбирается по языку сайта, можно задать явно в настройках
Лемматизация нет «люди» → «человек» не найдёт; за этим — ядро Manticore
Поиск с опечатками да многобайтный Левенштейн библиотеки (кириллица считается по символам)
Подсветка совпадений да текст экранируется до подсветки, наружу идут только <mark>
Вкладки по разделам да собственная карта «документ → раздел»
Веса разделов приблизительно полевых весов у движка нет: заголовок и ключевые слова повторяются в индексируемой строке, и BM25 поднимает их через частоту
Подсказка «возможно, вы имели в виду» нет
Сортировка по дате нет движок хранит только текст

Граница применимости

TNTSearch не хранит атрибутов и не фильтрует выдачу. Ядро забирает у него совпадения одним списком (по умолчанию до 2000 на запрос — настройка «Окно совпадений»), после чего фильтрует по разделам и режет на страницы само. Для сайта в тысячи документов это незаметно; когда типичный запрос начнёт упираться в потолок, пора переходить на ядро Manticore — контракт фасада, провайдеры модулей и вёрстка выдачи при этом не меняются.

Ориентир заявлен ядром в паспорте возможностей (comfortableSize) и виден на странице состояния индекса в админке.

Настройки (админка, раздел «Search»)

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

Служебные таблицы

Заводятся миграциями модуля при установке; содержимое полностью восстановимо переиндексацией — таблицы можно исключать из дампа базы:

  • search_tnt_map — карта «документ → раздел» по слотам;
  • search_tnt_state — какой слот сейчас рабочий.

Кроме них есть таблицы самого индекса — bescms_search_a_* и bescms_search_b_* (по пять на слот). Их создаёт и удаляет библиотека TNTSearch в момент пересборки, поэтому миграциями они не описываются: их жизненный цикл привязан к индексу, а не к установке модуля.

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

Требования

  • установленный и включённый модуль фасада Search;
  • MySQL-подключение (Yii::$app->db) — реквизиты берутся из него же, отдельных секретов не заводится;
  • DSN с host (TNTSearch подключается по TCP и не умеет unix-сокет);
  • ext-pdo, ext-mbstring.

Как ядро подключается к фасаду

Module реализует Besnovatyj\Search\contracts\SearchEngineProvider и объявляет один дескриптор: ключ tnt, подпись для настроек и класс движка. Больше фасаду ничего не нужно — он находит ядро обходом модулей и создаёт движок контейнером. Вся DI-проводка пакета живёт в src/config/common.php (секция container.singletons): ни config/container.php, ни Bootstrap-класса здесь нет, потому что к модулю ядра никто не обращается напрямую.