用 DuckDB 做全文检索:一份务实指南

查看原文 HN 讨论

文章摘要

Peter Doherty 这篇博客全面介绍了 DuckDB 的全文检索(FTS)扩展,目标读者是已经把 DuckDB 当作日常分析工具,但还没意识到它也能做”搜索”的工程师与数据分析师。文章的立场比较克制:DuckDB FTS 不会取代 Elasticsearch 或 PostgreSQL 的 tsvector/tsquery,但对于”探索性数据工作”(如本地分析邮件归档、爬虫输出、客户工单等),它已经”足够好用”。

安装与启用。DuckDB 默认不内置 FTS,需要手动加载:

INSTALL fts;
LOAD fts;

扩展通过运行时下载机制安装,这点也是 HN 评论中讨论较多的安全话题。

索引创建通过 PRAGMA 完成,可一次覆盖多列:

PRAGMA create_fts_index('emails', 'id', 'subject', 'body');

第二个参数是主键列;后面任意多列将一起被分词索引。可选参数包括:词干化(stemmer,默认是 Porter 风格的英文 stemmer,可换为其他语言)、停用词表、是否做重音归一化(accent folding)等。

查询机制基于 Okapi BM25 评分,调用形如:

SELECT id, score
FROM (
  SELECT *, fts_main_emails.match_bm25(id, 'invoice payment', fields := 'subject,body') AS score
  FROM emails
)
WHERE score IS NOT NULL
ORDER BY score DESC;

文章重点解释了 BM25 的两个调参常数:

与其他方案的对比:相比 PostgreSQL,DuckDB 缺少 ts_headline 这种”高亮匹配片段”功能,需要应用层自己实现。相比 SQLite FTS5,DuckDB 在分析型 SQL(窗口、聚合、Join)上远更强,但 SQLite FTS5 在写入吞吐和并发上更成熟。Elasticsearch 仍是大规模、近实时搜索的事实标准,DuckDB FTS 不打算与之竞争。

作者在结论中给出了实用判断:DuckDB FTS”相当强大,对大多数探索性场景足够”,特别适合需要”先做 ETL/分析、再做检索”的混合工作流——你可以一边做窗口聚合一边按相关性筛选,这是传统搜索引擎做不到的。

HN 评论精华