Как включить FTS5 для поиска строки по ".", "_" И "0-9"?

У меня есть таблица, содержащая 300К записей строк с использованием буквенно-цифровых символов, цифр, точек, подчеркивания и скобок [].

Я использую расширение FTS5 для sqlite3, чтобы включить быстрый поиск по этой таблице. Вот как я создаю виртуальную таблицу FTS:

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

Я добавляю записи ~300K, используя приведенный ниже код в цикле:

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 как действительные символы как часть токена.

Я попытался настроить токенизатор FTS с помощью tokenize = \"unicode61 tokenchars '_.'\" в заявлении о создании, но без везения.

Что мне не хватает?

2 ответа

Вот полный пример, чтобы понять, как tokenchars работает, потому что я думаю, что синтаксис довольно тонкий и легко ошибиться.

Давайте начнем с создания тестовой среды в оболочке:

$ sqlite3 ":memory:"

Теперь давайте создадим таблицу fts5, которая разрешит точку:

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

Тогда мы получим смутные бесполезные ошибки и неожиданные результаты, которые приведут нас к поиску в интернете, пытаясь выяснить, что мы делаем неправильно, и наткнуться на этот вопрос:)

Просто прошел через ту же проблему на другой платформе. Этот синтаксис работал для меня:

tokenize=unicode61 \"tokenchars=_.\"

Используйте FTS4, он может использовать "." для поиска

Другие вопросы по тегам