我想看一个完整的例子,因为我发现使用fts5很容易获得微妙和意想不到的结果。
首先,虽然包装搜索字符串可能会给你正确的答案,但它可能不是你真正想要的,这里有一个例子来说明:
$ sqlite3 ":memory:"
sqlite> CREATE VIRTUAL TABLE IF NOT EXISTS bad USING fts5(term, tokenize="unicode61");
sqlite>
sqlite> INSERT INTO bad (term) VALUES ('father''s');
sqlite>
sqlite> SELECT * from bad WHERE term MATCH 'father';
father's
sqlite> SELECT * from bad WHERE term MATCH '"father''s"';
father's
sqlite> SELECT * from bad WHERE term MATCH 's';
father's
注意s
比赛father's
也如何?那是因为当您运行father's
分词器时,默认情况下它将根据以下规则进行分词:
FTS5 裸字是一个或多个连续字符的字符串,它们都是:
- 非 ASCII 范围字符(即大于 127 的 unicode 代码点),或
- 52 个大写和小写 ASCII 字符之一,或
- 10 个十进制数字 ASCII 字符之一,或
- 下划线字符(unicode 代码点 96)。
- 替代字符(unicode 代码点 26)。
所以father's
会被标记为father
and s
,这可能是也可能不是你想要的,但为了这个答案,我假设这不是你想要的。
那么你会如何告诉标记器保持father's
在一起呢?通过使用参数的tokenchars
选项tokenize
:
tokenchars 此选项用于指定应被视为标记字符的附加 Unicode 字符,即使它们是根据 Unicode 6.1 的空白或标点字符。此选项设置为的字符串中的所有字符都被视为标记字符。
让我们看另一个例子,这次使用tokenchars
:
$ sqlite3 ":memory:"
sqlite> CREATE VIRTUAL TABLE IF NOT EXISTS good USING fts5(term, tokenize="unicode61 tokenchars '''&:'");
sqlite>
sqlite> INSERT INTO good (term) VALUES ('father''s');
sqlite> INSERT INTO good (term) VALUES ('month&');
sqlite> INSERT INTO good (term) VALUES ('example:');
sqlite>
sqlite> SELECT count(*) from good WHERE term MATCH 'father';
0
sqlite> SELECT count(*) from good WHERE term MATCH '"father''s"';
1
sqlite> SELECT count(*) from good WHERE term MATCH 'example';
0
sqlite> SELECT count(*) from good WHERE term MATCH '"example:"';
1
sqlite> SELECT count(*) from good WHERE term MATCH 'month';
0
sqlite> SELECT count(*) from good WHERE term MATCH '"month&"';
1
这些结果似乎更令人期待。但是s
第一个例子的随机结果呢?
sqlite> SELECT count(*) from good WHERE term MATCH 's';
0
伟大的!
希望这可以帮助您按照预期的方式设置表格。