Как включить 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
дает следующее:
ext
: ничего такогоextbootrecord
: все записиextbootrecrd.
: все записиextbootrecord.fie
: ничего такогоextbootrecord.field
: все записи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=_.\"