SQLite FTS5 за один вечер

28 июня 2026 1 мин чтения
pythonsqliteзаметки

Полнотекстовый поиск звучит как что-то тяжёлое. На самом деле в SQLite он уже встроен — достаточно одной виртуальной таблицы.

Создаём индекс#

CREATE VIRTUAL TABLE notes_fts USING fts5(
  title, body, content='notes', content_rowid='id'
);

Держим индекс в актуальном состоянии#

Три триггера — и записи синхронизируются автоматически:

CREATE TRIGGER notes_ai AFTER INSERT ON notes BEGIN
  INSERT INTO notes_fts(rowid, title, body) VALUES (new.id, new.title, new.body);
END;

Запрос#

rows = db.execute(
    "SELECT rowid, snippet(notes_fts, 1, '[', ']', '…', 8) "
    "FROM notes_fts WHERE notes_fts MATCH ? ORDER BY rank",
    (query,),
).fetchall()

snippet() сам подсветит совпадение, rank отсортирует по релевантности.

Что стоит помнить#

  • токенизатор по умолчанию плохо дружит с русской морфологией — помогает unicode61 remove_diacritics 2;
  • MATCH не любит пользовательский ввод как есть: экранируйте кавычки;
  • на десятках тысяч записей поиск отрабатывает за единицы миллисекунд.

Вечер работы — и внешний поисковый движок не нужен.