SonnetDB 全文搜索入门:CREATE FULLTEXT INDEX、match 与 BM25
SonnetDB 的全文搜索建立在 JSON document collection 之上。主数据是文档集合,全文索引是可重建的派生索引。这个边界很重要:删除索引不会删除文档,索引目录丢失后也可以从主数据重建。
下面是 C# 里的完整流程。
using SonnetDB.Engine;
using SonnetDB.Sql;
using SonnetDB.Sql.Execution;
using var db = Tsdb.Open(new TsdbOptions
{
RootDirectory = "data/fulltext-demo"
});
SqlExecutor.Execute(db, "CREATE DOCUMENT COLLECTION logs");
SqlExecutor.Execute(db, """
INSERT INTO logs (id, document)
VALUES
('log-1', '{"message":"Pump alarm in north station","level":"warn"}'),
('log-2', '{"message":"Fan alarm cleared","level":"info"}'),
('log-3', '{"message":"Pump pressure normal","level":"info"}')
""");
SqlExecutor.Execute(db, """
CREATE FULLTEXT INDEX ft_logs_message
ON logs ('$.message')
USING unicode
""");
var result = (SelectExecutionResult)SqlExecutor.Execute(db, """
SELECT id, bm25_score() AS score
FROM logs
WHERE match(ft_logs_message, '$.message', 'pump alarm', 5)
ORDER BY score DESC
""");
foreach (var row in result.Rows)
{
Console.WriteLine($"{row[0]} score={row[1]}");
}
match(index, field, query, topK) 必须作为 WHERE 里的独立谓词使用。bm25_score() 只能出现在包含全文匹配的文档查询中,用于投影或排序。
多字段索引
如果一份文档同时有标题和正文,可以把两个 JSON path 放进同一个全文索引:
SqlExecutor.Execute(db, """
CREATE DOCUMENT COLLECTION articles
""");
SqlExecutor.Execute(db, """
CREATE FULLTEXT INDEX ft_articles_all
ON articles ('$.title', '$.body')
USING unicode
""");
var hits = (SelectExecutionResult)SqlExecutor.Execute(db, """
SELECT id
FROM articles
WHERE match(ft_articles_all, *, 'pump maintenance', 20)
""");
* 表示在这个全文索引的所有字段里搜索。
中文分词器
当前支持 unicode、cjk 和 jieba。如果文档主要是中文,可以这样声明:
SqlExecutor.Execute(db, """
CREATE FULLTEXT INDEX ft_workorders_body
ON workorders ('$.body')
USING jieba
""");
对工业知识库来说,全文搜索解决的是“文本关键词”问题。它和向量搜索并不是替代关系:全文搜索擅长精确词命中,向量搜索擅长语义相似。真正的知识检索通常需要下一篇要讲的 Hybrid Search。
官网地址:https://sonnetdb.com
技术文章站:https://iotpaper.net

浙公网安备 33010602011771号