不止一叶代码屋 个人技术博客 · 代码与生活的记录

数据库

用 SQLite FTS5 给静态博客做全文搜索

起因

博客文章上了二十篇之后,自己翻起来都费劲。想加搜索,但为了一个静态博客装 Elasticsearch 实在小题大做。

试了一下 SQLite 内置的 FTS5,发现完全够用。

建表

FTS5 需要一张「虚表」,内容和主表分开存:

CREATE VIRTUAL TABLE posts_fts USING fts5(
  title,
  summary,
  content,
  content='posts',
  content_rowid='id',
  tokenize='unicode61'
);

content='posts' 表示内容和主表共用,不额外占空间。

中文分词

默认的 unicode61 对中文是逐字切分的,效果一般但能用。想要更准就上 jieba 或者 simple 分词器,不过编译麻烦。

unicode61 配合「加空格 = 切词」的策略,在博客这种场景下召回率其实不差。

查询

SELECT p.id, p.title,
       snippet(posts_fts, 2, '<mark>', '</mark>', '…', 24) AS hit
FROM posts_fts
JOIN posts p ON p.id = posts_fts.rowid
WHERE posts_fts MATCH ?
ORDER BY rank
LIMIT 10;

snippet() 直接帮你把命中片段摘出来,省得自己写高亮逻辑。

维护

主表改动后要同步虚表,用触发器最简单:

CREATE TRIGGER posts_ai AFTER INSERT ON posts BEGIN
  INSERT INTO posts_fts(rowid, title, summary, content)
  VALUES (new.id, new.title, new.summary, new.content);
END;

删除和更新同理写两个。加上之后基本不用管了。

小结

全文搜索这件事,需求不大的话真没必要上重型组件。SQLite 的 FTS5 大概是最低成本的方案。

订阅 RSS

← 返回首页