Самый простой ответ
Я использую простой sql ниже, чтобы все было максимально понятно и читабельно. В своем проекте вы можете использовать удобные методы Android. db
Объект , используемый ниже , является экземпляром SQLiteDatabase .
Создать таблицу FTS
db.execSQL("CREATE VIRTUAL TABLE fts_table USING fts3 ( col_1, col_2, text_column )");
Это может быть в onCreate()
методе вашего расширенного SQLiteOpenHelper
класса.
Заполнить таблицу FTS
db.execSQL("INSERT INTO fts_table VALUES ('3', 'apple', 'Hello. How are you?')");
db.execSQL("INSERT INTO fts_table VALUES ('24', 'car', 'Fine. Thank you.')");
db.execSQL("INSERT INTO fts_table VALUES ('13', 'book', 'This is an example.')");
Было бы лучше использовать SQLiteDatabase # insert или подготовленные операторы, чем execSQL
.
Запросить таблицу FTS
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_table WHERE fts_table MATCH ?", selectionArgs);
Вы также можете использовать метод запроса SQLiteDatabase # . Обратите внимание на MATCH
ключевое слово.
Более полный ответ
В виртуальной таблице FTS выше есть проблема. Индексируется каждый столбец, но это пустая трата места и ресурсов, если некоторые столбцы не нужно индексировать. Единственный столбец, который нуждается в индексе FTS, вероятно,text_column
.
Для решения этой проблемы мы будем использовать комбинацию обычной таблицы и виртуальной таблицы FTS. Таблица FTS будет содержать индекс, но не фактические данные из обычной таблицы. Вместо этого у него будет ссылка на содержимое обычной таблицы. Это называется таблицей внешнего содержимого .
Создайте таблицы
db.execSQL("CREATE TABLE example_table (_id INTEGER PRIMARY KEY, col_1 INTEGER, col_2 TEXT, text_column TEXT)");
db.execSQL("CREATE VIRTUAL TABLE fts_example_table USING fts4 (content='example_table', text_column)");
Обратите внимание, что для этого мы должны использовать FTS4, а не FTS3. FTS4 не поддерживается в Android до версии 11 API. Вы можете либо (1) предоставить функцию поиска только для API> = 11, либо (2) использовать таблицу FTS3 (но это означает, что база данных будет больше, поскольку существует полнотекстовый столбец. в обеих базах данных).
Заполните таблицы
db.execSQL("INSERT INTO example_table (col_1, col_2, text_column) VALUES ('3', 'apple', 'Hello. How are you?')");
db.execSQL("INSERT INTO example_table (col_1, col_2, text_column) VALUES ('24', 'car', 'Fine. Thank you.')");
db.execSQL("INSERT INTO example_table (col_1, col_2, text_column) VALUES ('13', 'book', 'This is an example.')");
(Опять же, есть лучшие способы вставки do, чем с execSQL
. Я использую его просто для удобства чтения.)
Если вы попытаетесь выполнить запрос FTS сейчас, fts_example_table
вы не получите результатов. Причина в том, что изменение одной таблицы не приводит к автоматическому изменению другой таблицы. Вам необходимо вручную обновить таблицу FTS:
db.execSQL("INSERT INTO fts_example_table (docid, text_column) SELECT _id, text_column FROM example_table");
(Это docid
похоже на rowid
обычную таблицу.) Вы должны обязательно обновлять таблицу FTS (чтобы она могла обновлять индекс) каждый раз, когда вы вносите изменения (INSERT, DELETE, UPDATE) во внешнюю таблицу содержимого. Это может стать громоздким. Если вы создаете только предварительно заполненную базу данных, вы можете сделать
db.execSQL("INSERT INTO fts_example_table(fts_example_table) VALUES('rebuild')");
который перестроит всю таблицу. Однако это может быть медленным, поэтому вам не стоит делать это после каждого небольшого изменения. Вы должны сделать это после завершения всех вставок во внешнюю таблицу содержимого. Если вам действительно нужно поддерживать синхронизацию баз данных автоматически, вы можете использовать триггеры . Идите сюда и прокрутите немного вниз, чтобы найти дорогу.
Запрос баз данных
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_example_table WHERE fts_example_table MATCH ?", selectionArgs);
Это то же самое, что и раньше, за исключением того, что на этот раз у вас есть доступ только к text_column
(и docid
). Что делать, если вам нужно получить данные из других столбцов во внешней таблице содержимого? Поскольку docid
таблица FTS соответствует rowid
(и в данном случае _id
) таблице внешнего содержимого, вы можете использовать соединение. (Спасибо этому ответу за помощь.)
String sql = "SELECT * FROM example_table WHERE _id IN " +
"(SELECT docid FROM fts_example_table WHERE fts_example_table MATCH ?)";
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery(sql, selectionArgs);
Дальнейшее чтение
Внимательно ознакомьтесь с этими документами, чтобы увидеть другие способы использования виртуальных таблиц FTS:
Дополнительные примечания