D1 全文搜索踩坑记

用 SQLite FTS5 给中文博客做搜索,分词是最大的坑。


FTS5 默认的 unicode61 分词器会把一整段连续的中文当成一个词,所以搜“搜索”永远命中不了“全文搜索”。

我的做法

不引入分词库,而是在建索引时把每个汉字拆开,查询时把连续的汉字当成一个短语:

const CJK = /[\u4e00-\u9fff]/gu;
export function tokenize(text: string): string {
  return text.toLowerCase().replace(CJK, (c) => ` ${c} `).replace(/\s+/g, ' ').trim();
}

查询“搜索”变成 "搜 索",FTS5 会要求这两个字相邻出现,既不会漏,也不会把“搜…索”分散出现的文章带出来。

还要防什么

用户输入不能直接拼进 MATCH,"、*、NEAR 都是语法。我的办法是先分词,把所有符号丢掉,再给每个词加引号。

索引示意

输入 查询
搜索 "搜 索"
d1 踩坑 "d1" "踩 坑"

评论 0