首页 > 解决方案 > SQLite FTS5 Match 什么也不返回

问题描述

我有一个 SQLite3 表:

CREATE TABLE "test" (
    "title" TEXT,
    "shortdesc" TEXT,
    "longdesc"  TEXT,
    "id"    TEXT,
    PRIMARY KEY("id")
);

我在其中插入任何内容:

INSERT INTO test (id, title, shortdesc, longdesc) VALUES ("abc", "hello world", "this is a hello world", "a nice hello world article about hello worlds")

然后我创建一个 FTS5 虚拟表:

CREATE VIRTUAL TABLE IF NOT EXISTS test_fts USING fts5 (
        id,
        title,
        shortdesc,
        longdesc,
        content=test
);

所以我检查虚拟表中的数据:

截屏

一切似乎都很好......现在我尝试使用MATCH来查找文章:

SELECT * FROM test_fts WHERE test_fts MATCH 'hello'

...我没有得到任何结果。显然我展示的这个数据库只是一个例子,实际数据库也会发生同样的事情。我在不同的计算机(和不同的客户端)上尝试过,我还检查了 FTS5 是否已启用并在其中编译,PRAGMA compile_options并且ENABLE_FTS5是否存在,这意味着它已启用。FTS3 和 4 也会发生同样的情况。

那么我错过了什么?SQLite 版本是 3.36.0。

标签: sqlitefull-text-searchfts3fts4fts5

解决方案


FTS5 表仍需要填充。这包括外部内容案例。从文档中:

用户仍有责任确保外部内容 FTS5 表的内容与内容表保持同步。一种方法是使用触发器。例如:

-- Create a table. And an external content fts5 table to index it.
CREATE TABLE tbl(a INTEGER PRIMARY KEY, b, c);
CREATE VIRTUAL TABLE fts_idx USING fts5(b, c, content='tbl', content_rowid='a');

-- Triggers to keep the FTS index up to date.
CREATE TRIGGER tbl_ai AFTER INSERT ON tbl BEGIN
 INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c);
END;
CREATE TRIGGER tbl_ad AFTER DELETE ON tbl BEGIN
 INSERT INTO fts_idx(fts_idx, rowid, b, c) VALUES('delete', old.a, old.b, old.c);
END;
CREATE TRIGGER tbl_au AFTER UPDATE ON tbl BEGIN
 INSERT INTO fts_idx(fts_idx, rowid, b, c) VALUES('delete', old.a, old.b, old.c);
 INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c);
END;

因此,您可以在填充主表之前创建表和触发器,或者在您的测试用例中,在创建 FTS 表之后,您可以运行这样的查询来首次填充 FTS 表:

INSERT INTO test_fts SELECT * FROM test;

然后您的查询将按预期工作。


推荐阅读