SQLite FTS5 за один вечер
Полнотекстовый поиск звучит как что-то тяжёлое. На самом деле в 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не любит пользовательский ввод как есть: экранируйте кавычки;- на десятках тысяч записей поиск отрабатывает за единицы миллисекунд.
Вечер работы — и внешний поисковый движок не нужен.