Sqlite FTS5 标点符号在选择查询中不起作用
Posted
技术标签:
【中文标题】Sqlite FTS5 标点符号在选择查询中不起作用【英文标题】:Sqlite FTS5 punctuation marks not working in select query 【发布时间】:2017-05-15 13:41:14 【问题描述】:我正在使用 sqlite 进行全文搜索,以下是我正在使用的一些选择查询示例。
例如:
SELECT * FROM table WHERE table MATCH 'column:father's' ORDER BY rank;
SELECT * FROM table WHERE table MATCH 'column:example:' ORDER BY rank;
SELECT * FROM table WHERE table MATCH 'column:month&' ORDER BY rank;由于我在搜索文本中使用 ' : & 字符,因此这些查询给了我错误。我也尝试在标点符号前使用转义字符(\-反斜杠)。
在fts5中使用MATCH操作符搜索标点符号(, . / " ' - & etc.)有什么解决办法吗?
这些字符与匹配运算符一起使用 _、€、£、¥
谢谢
【问题讨论】:
【参考方案1】:我想看一个完整的例子,因为我发现使用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
时,它将根据the following rules by default 进行标记:
FTS5 裸字是一个或多个连续字符的字符串 这些都是:
非 ASCII 范围字符(即大于 127 的 unicode 代码点),或 52 个大小写 ASCII 字符之一,或 10 个十进制数字 ASCII 字符之一,或 下划线字符(unicode 代码点 96)。 替代字符(unicode 代码点 26)。
所以father's
将被标记为father
和s
,这可能是也可能不是你想要的,但为了这个答案,我假设这不是你想要的。
那么你会如何告诉tokenizer 保持father's
在一起?通过使用tokenize
参数的tokenchars
选项:
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
太棒了!
希望这可以帮助您按预期方式设置表格。
【讨论】:
【参考方案2】:这似乎与this question 重复。尝试那里的最佳答案,指出您应该将搜索字符串用单引号和双引号括起来。
【讨论】:
【参考方案3】:# fathers'
SELECT * FROM table WHERE table MATCH 'column:"father''s"';
# example:
SELECT * FROM table WHERE table MATCH 'column:"example:"';
# month&
SELECT * FROM table WHERE table MATCH 'column:"month&"';
【讨论】:
以上是关于Sqlite FTS5 标点符号在选择查询中不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Peewee 可以使用 SQLite 的 FTS5(全文搜索)辅助函数 highlight() 吗?
如何使用带有 Python 3.7 的 sqlite3 python 模块的 FTS5 扩展?
如何在 Peewee 和 SQLite 的 FTS5 中使用 trigram tokenizer/similarity 选项?
如何在 Ubuntu 16.04 上将 FTS5 扩展与带有 Python 3.7 的 sqlite3 python 模块一起使用?