【问题标题】:How to enable FTS5 search a string with ".", "_" and "0-9"?如何启用 FTS5 搜索带有“.”、“_”和“0-9”的字符串?
【发布时间】:2017-08-14 19:24:12
【问题描述】:

我有一个表格,其中包含 30 万条使用字母数字、数字、点、下划线和方括号 [] 的字符串记录。

我使用对 sqlite3 的 FTS5 扩展来启用对该表的快速搜索。 这就是我创建 FTS 虚拟表的方式:

database = sqlite3.connect("mydb.db")
db_cursor = database.cursor()
db_cursor.execute("create virtual table field_names USING fts5 (full_path)")

我在循环中使用以下代码添加约 30 万条记录:

database.execute("insert into field_names(full_path) values (?)", (field_path,))

样本记录:

a.extbootrecord.field_db0    
a.extbootrecord.field_db1    
a.extbootrecord.field_db8    
a.extbootrecord.field_db9    
a.extbootrecord.field_db10   
a.extbootrecord.field_db11   
a.extbootrecord.field_db12   
a.extbootrecord.field_db15   

使用以下查询:

db_cursor.execute("select full_path from field_names where field_names = '\"%s\"'" % search_phrase)
return_list = list()

entries = db_cursor.fetchmany(100)
while entries:
    return_list.extend([entry[0] for entry in entries])
    entries = db_cursor.fetchmany(100)

使用以下search_phrase 会产生以下结果:

  1. ext:没什么
  2. extbootrecord:所有记录
  3. extbootrecrd.:所有记录
  4. extbootrecord.fie:没什么
  5. extbootrecord.field : 所有记录
  6. extbootrecord.field_db1 :只有 a.extbootrecord.field_db1 记录,我希望 field_db1, field_db10, field_db11... 被返回

似乎我缺少一些 FTS 配置来使用 ._0-9 作为令牌的一部分作为有效字符。

我尝试在创建语句中使用 tokenize = \"unicode61 tokenchars '_.'\" 配置 FTS 标记器,但没有成功。

我错过了什么?

【问题讨论】:

    标签: python-3.x sqlite full-text-search fts5


    【解决方案1】:

    这里有一个完整的例子来说明tokenchars 的工作原理,因为我认为语法相当微妙并且容易出错。

    让我们首先在 shell 中创建一个测试环境:

    $ sqlite3 ":memory:"
    

    现在让我们创建一个fts5 table 来允许句点:

    sqlite> CREATE VIRTUAL TABLE IF NOT EXISTS foo USING fts5(name UNINDEXED, keywords, tokenize="unicode61 tokenchars '.'");
    

    注意tokenize 值是如何设置的,您将双引号括在值周围,将单引号括在要添加的tokenchars 周围(我们只是在此处添加句点,但您可以添加任意数量的字符想要)。

    我们的表准备好了,我们准备插入一些值:

    sqlite> INSERT INTO foo (name, keywords) VALUES ('bar', '1.0');
    sqlite> INSERT INTO foo (name, keywords) VALUES ('che', '1.5');
    sqlite> INSERT INTO foo (name, keywords) VALUES ('baz', '2.5');
    

    然后搜索这些值:

    sqlite> SELECT name from foo WHERE keywords MATCH '"1."*';
    bar
    che
    sqlite> SELECT name from foo WHERE keywords MATCH '"1.5"*';
    che
    sqlite> SELECT name from foo WHERE keywords MATCH '"2"*';
    baz 
    

    请注意,如果我们的搜索字符串中有句点,我们必须如何搜索值,我们必须将搜索字符串用双引号括起来(如果我们想要进行前缀搜索,则在这些双引号之外添加星号) 然后像往常一样将整个字符串用单引号括起来。

    如果我们不使用双引号:

    sqlite> SELECT name from foo WHERE keywords MATCH '1.*';
    Error: fts5: syntax error near "."
    

    或者我们错误地使用了双引号:

    sqlite> SELECT count(*) from foo WHERE keywords MATCH '1"."*';
    0
    

    然后我们会得到模糊的无用错误和意想不到的结果,这将导致我们搜索互联网试图找出我们做错了什么并偶然发现这个问题:)

    【讨论】:

      【解决方案2】:

      刚刚在不同的平台上遇到了同样的问题。这种语法对我有用:

      tokenize=unicode61 \"tokenchars=_.\"
      

      【讨论】:

        【解决方案3】:

        使用 FTS4 它可以使用“。”用于搜索

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-05
          • 2012-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-22
          相关资源
          最近更新 更多