我正在使用SQLite的FTS模块尝试使用窗口(或某些人可能称之为分页)的结果来实现全文搜索,以及突出显示每个窗口内的搜索命中。据我所知,可以直接对或高亮显示搜索命中,但不能两者兼而有之。
为了实现窗口,我运行FTS并检索并存储临时表中每个命中的docid,如下所示:
CREATE VIRTUAL TABLE FullTextIndex USING FTS4 ( fulltext TEXT );
...
CREATE TEMP TABLE SearchResults ( id INTEGER );
INSERT INTO SearchResults
SELECT docid FROM FullTextIndex WHERE fullText MATCH 'mySearchExpression';
当我准备根据窗口标准检索实际的全文时,我会这样做:
SELECT FullTextIndex.fullText FROM FullTextIndex
INNER JOIN SearchResults
ON FullTextIndex.docid = SearchResults.id
WHERE *windowing criteria applied to SearchResults*;
这部分效果很好而且非常有效,因为它是一个rowid匹配。
但是,此时我无法使用SQLite的snippet
函数(或任何其他FTS辅助函数)来突出显示我的搜索命中,因为我没有使用文本查询中的索引。因此我尝试了这个:
SELECT snippet(FullTextIndex) FROM FullTextIndex
WHERE FullTextIndex.docID IN
(SELECT id FROM SearchResults WHERE *windowing criteria*)
AND FullTextIndex.fullText MATCH 'mySearchExpression';
它有效,但它几乎与原始FTS一样长,因为它显然首先运行FTS,而没有应用基于SearchResults
的缩小标准(我认为基本上它不能因为方式FTS索引工作)。
到目前为止,我的最佳解决方案是创建第二个临时表 - 一个临时全文索引,仅包含每个窗口的搜索命中。实质上这是:
CREATE VIRTUAL TABLE temp.TextResultsWindow USING FTS4 (id INTEGER, fullText text);
INSERT INTO temp.TextResultsWindow
SELECT FullTextIndex.docid, FullTextIndex.fullText
FROM FullTextIndex
WHERE FullTextIndex.docid IN
(SELECT id from SearchResults WHERE *windowing criteria*);
SELECT snippet(temp.TextResultsWindow.TextResultsWindow)
FROM temp.TextResultsWindow
WHERE temp.TextResultsWindow.fullText
MATCH 'mySearchExpression';
这确实有效,对于适度的窗口大小来说似乎相对较快,但是重新索引搜索命中窗口只是为了突出显示效率似乎非常低效。如果特定窗口中的文本量非常大,我也可以很容易地看到窗口检索比原始FTS花费的时间更长,只是因为它必须花费这么多时间为每个窗口重新索引才使用{{ 1}}功能。因此,虽然它在学术上有效,但我认为它在实践中不会很好。
有人能提出更好的方法吗?许多应用程序都具有全文搜索功能,包括窗口和突出显示。我别无选择,只能对我检索的每个全文结果应用手动扫描和突出显示功能吗?
非常感谢。
更新:
对于它的价值,有一个section in the SQLite documentation讨论了FTE3 / 4和snippet
,以及分页/窗口。他们建议使用LIMIT和OFFSET来进行窗口化,因此他们描述的场景确实会导致在每个窗口的整个索引上重新运行全文搜索。我想如果SQLite开发人员没有更有效的方法来做到这一点它可能不存在,但仍然会欣赏人们可能有的任何其他想法。