SQLite LinuxWindowsmacOS

Почему FTS5 MATCH не находит слово после изменения токенизатора

  • Обновлено
  • Чтение ≈ 3 минуты

Краткий ответ

FTS5 сравнивает не исходную строку посимвольно, а последовательность токенов, которую определяет параметр tokenize при создании виртуальной таблицы. Например, если дефис включён в tokenchars, «usb-c» будет одним токеном, и поиск слова «usb» его не найдёт. Без такого параметра unicode61 обычно делит строку на «usb» и «c». Изменение токенизатора требует согласованного нового индекса; обычный REBUILD не меняет определение tokenize.

В этой статье
  1. Что происходит и когда возникает
  2. Возможные причины: как различить
  3. Пошаговая диагностика и исправление
  4. Команды и проверочные примеры
  5. Как проверить результат
  6. Если не помогло

#Что происходит и когда возникает

FTS5 сравнивает не исходную строку посимвольно, а последовательность токенов, которую определяет параметр tokenize при создании виртуальной таблицы. Например, если дефис включён в tokenchars, «usb-c» будет одним токеном, и поиск слова «usb» его не найдёт. Без такого параметра unicode61 обычно делит строку на «usb» и «c». Изменение токенизатора требует согласованного нового индекса; обычный REBUILD не меняет определение tokenize.

#Возможные причины: как различить

Возможная причинаКак узнатьЧто делать
Дефис/подчёркивание стали частью токенаОпция tokenchars включает разделитель внутрь слова.MATCH usb не находит запись usb-c; точная фраза с дефисом может находиться.Согласовать tokenchars и построить новый индекс.
Поиск части слова вместо токенаunicode61 не делает автоматического поиска произвольных подстрок и не выполняет русское склонение.«ошиб» не находит «ошибка», а «ошиб*» может найти.Использовать поддерживаемый префиксный запрос либо другую модель поиска.
Индекс отстаёт от исходной таблицыДля external-content индекса триггеры могли не перенести изменения.Прямой SELECT видит строку, а MATCH — нет после INSERT/UPDATE.Проверить триггеры синхронизации и отдельно выполнить rebuild индекса.

#Пошаговая диагностика и исправление

  1. Уточните точное поисковое слово и записьНайдите в исходной таблице проблемную строку, её идентификатор и текст. Сохраните исходный запрос MATCH без пользовательских секретов. Разделите случаи «слово не разбивается» и «запись вообще не попала в индекс»: это две разные ошибки.
  2. Посмотрите определение таблицы FTS5Откройте SQL-консоль на копии базы и выполните SELECT sql FROM sqlite_schema WHERE name='search_fts';, подставив имя вашей виртуальной таблицы. Найдите tokenize, tokenchars, separators, prefix, content. Если tokenize не указан, обычно используется unicode61. Не изменяйте схему, пока не проверили конкретные правила.
  3. Проверьте доступность расширения FTS5В консоли для своей базы выполните SELECT sqlite_version(); и PRAGMA compile_options;. При попытке CREATE VIRTUAL TABLE может быть ошибка «no such module: fts5»; в таком случае проверьте используемую сборку и не пытайтесь исправлять отсутствующий модуль настройками MATCH.
  4. Воспроизведите влияние дефиса в отдельной базеВ новой тестовой SQLite-базе создайте FTS5 с параметром tokenchars для дефиса, вставьте «usb-c» и выполните запросы из учебного примера. Если MATCH 'usb' ничего не возвращает, а точная фраза возвращает строку, причина — токенизация, а не отсутствие записи.
  5. Проверьте различие между словом, префиксом и подстрокойЕсли пользователь вводит «ошиб», испытайте MATCH 'ошиб*' на тестовой таблице: звёздочка означает поиск по началу токена. Для символов дефиса и операторов FTS5 используйте корректно экранированные фразы, иначе парсер MATCH может воспринимать ввод как синтаксис запроса.
  6. Проверьте обновление индекса при отдельной исходной таблицеЕсли используется content='имя_таблицы', изучите триггеры INSERT/UPDATE/DELETE, которые поддерживают внешний индекс. Без них данные могли появиться в исходной таблице, но не в FTS5. На копии после исправления синхронизации применяйте рекомендованный для FTS5 rebuild и проверяйте соответствие, не запускайте rebuild на занятой базе без окна и резервной копии.
  7. Пересоздайте индекс с нужными правилами только после тестовЕсли политика поиска требует другой токенизатор, создайте новую FTS5-таблицу с другим именем в копии, заполните из исходных записей, проверьте контрольные запросы и только затем согласуйте переключение приложения. Существующий индекс и старые записи не удаляйте до подтверждения результата и возможности отката.

#Команды и проверочные примеры

SQLКоманда
search_fts — пример, замените именем фактической FTS5-таблицы. Только чтение.
SELECT sql FROM sqlite_schema WHERE name='search_fts';
SELECT sqlite_version();
SQL
Отдельная тестовая база. При объединённом токене ожидаются результаты 0 и 1; при другой версии или сборке сначала проверьте поддержку tokenizer.
CREATE VIRTUAL TABLE demo_fts USING fts5(text, tokenize="unicode61 tokenchars '-_'");
INSERT INTO demo_fts VALUES ('usb-c');
SELECT count(*) FROM demo_fts WHERE demo_fts MATCH 'usb';
SELECT count(*) FROM demo_fts WHERE demo_fts MATCH '"usb-c"';

#Как проверить результат

Тестовый поиск находит специально выбранные контрольные слова, знаки и префиксы; пересозданный индекс содержит ожидаемое число записей. Убедитесь, что изменения в исходных строках отображаются в поиске после INSERT/UPDATE/DELETE.

#Если не помогло

Если выдача пустая только для новых строк, изучите модель external-content и триггеры. Если не находится отдельное слово внутри «usb-c», повторно проверьте tokenchars и экранирование MATCH. Для сложных языковых форм понадобится отдельная нормализация или поисковый механизм.

Источники и обновления

Последнее обновление статьи: 2 ноября 2026. Версии программ и интерфейсы меняются — если шаги не совпадают с вашей версией, сверяйтесь с документацией производителя.