Najbardziej podstawowa odpowiedź
Używam zwykłego sql poniżej, aby wszystko było tak jasne i czytelne, jak to tylko możliwe. W swoim projekcie możesz skorzystać z wygodnych metod Androida. db
Przedmiot używany poniżej jest przykładem SQLiteDatabase .
Utwórz tabelę FTS
db.execSQL("CREATE VIRTUAL TABLE fts_table USING fts3 ( col_1, col_2, text_column )");
Może to dotyczyć onCreate()
metody rozszerzonej SQLiteOpenHelper
klasy.
Wypełnij tabelę 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.')");
Byłoby lepiej użyć SQLiteDatabase # insert lub przygotowanych instrukcji niż execSQL
.
Zapytanie o tabelę FTS
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_table WHERE fts_table MATCH ?", selectionArgs);
Możesz również użyć metody zapytania SQLiteDatabase # . ZanotujMATCH
słowo kluczowe.
Pełniejsza odpowiedź
Powyższa wirtualna tabela FTS ma z tym problem. Każda kolumna jest indeksowana, ale jest to strata miejsca i zasobów, jeśli niektóre kolumny nie muszą być indeksowane. Jedyną kolumną, która wymaga indeksu FTS, jest prawdopodobnietext_column
.
Aby rozwiązać ten problem, użyjemy kombinacji zwykłej tabeli i wirtualnej tabeli FTS. Tabela FTS będzie zawierać indeks, ale żadnych rzeczywistych danych ze zwykłej tabeli. Zamiast tego będzie zawierał link do zawartości zwykłej tabeli. Nazywa się to tabelą zawartości zewnętrznej .
Utwórz tabele
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)");
Zauważ, że musimy do tego użyć FTS4 zamiast FTS3. FTS4 nie jest obsługiwany w Androidzie przed wersją API 11. Możesz albo (1) zapewnić funkcjonalność wyszukiwania tylko dla API> = 11, albo (2) użyć tabeli FTS3 (ale to oznacza, że baza danych będzie większa ponieważ istnieje kolumna pełnego tekstu w obu bazach danych).
Wypełnij tabele
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.')");
(Ponownie, są lepsze sposoby na wstawianie niż z execSQL
. Używam go tylko ze względu na jego czytelność).
Jeśli spróbujesz teraz wykonać zapytanie FTS fts_example_table
, nie uzyskasz żadnych wyników. Powodem jest to, że zmiana jednej tabeli nie zmienia automatycznie drugiej tabeli. Musisz ręcznie zaktualizować tabelę FTS:
db.execSQL("INSERT INTO fts_example_table (docid, text_column) SELECT _id, text_column FROM example_table");
(To docid
jest jak rowid
dla zwykłej tabeli.) Musisz upewnić się, że zaktualizujesz tabelę FTS (tak, aby mogła aktualizować indeks) za każdym razem, gdy dokonujesz zmiany (INSERT, DELETE, UPDATE) w zewnętrznej tabeli zawartości. Może to być kłopotliwe. Jeśli tworzysz tylko wstępnie wypełnioną bazę danych, możesz to zrobić
db.execSQL("INSERT INTO fts_example_table(fts_example_table) VALUES('rebuild')");
który odbuduje cały stół. Może to jednak być powolne, więc nie jest to coś, co chcesz robić po każdej drobnej zmianie. Zrobiłbyś to po zakończeniu wszystkich wstawień w zewnętrznej tabeli zawartości. Jeśli musisz automatycznie synchronizować bazy danych, możesz użyć wyzwalaczy . Przejdź tutaj i przewiń trochę w dół, aby znaleźć wskazówki.
Przeszukuj bazy danych
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_example_table WHERE fts_example_table MATCH ?", selectionArgs);
To jest to samo co poprzednio, z tym że tym razem masz dostęp tylko do text_column
(i docid
). Co się stanie, jeśli chcesz pobrać dane z innych kolumn w tabeli zawartości zewnętrznej? Ponieważ docid
tabela FTS pasuje do rowid
(iw tym przypadku _id
) tabeli zawartości zewnętrznej, możesz użyć sprzężenia. (Dzięki tej odpowiedzi za pomoc.)
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);
Dalsze czytanie
Przejrzyj dokładnie te dokumenty, aby zobaczyć inne sposoby korzystania z wirtualnych tabel FTS:
Dodatkowe uwagi