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 将被标记为fathers,这可能是也可能不是你想要的,但为了这个答案,我假设这不是你想要的。

那么你会如何告诉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() 吗?

安卓 SQLITE FTS 版本

如何使用带有 Python 3.7 的 sqlite3 python 模块的 FTS5 扩展?

如何在 Peewee 和 SQLite 的 FTS5 中使用 trigram tokenizer/similarity 选项?

C# SQLite FTS5 表和触发器创建

如何在 Ubuntu 16.04 上将 FTS5 扩展与带有 Python 3.7 的 sqlite3 python 模块一起使用?