Jawaban Paling Dasar
Saya menggunakan sql biasa di bawah ini sehingga semuanya sejelas dan terbaca. Dalam proyek Anda, Anda dapat menggunakan metode kenyamanan Android. The db
objek yang digunakan di bawah ini adalah sebuah contoh dari SQLiteDatabase .
Buat Tabel FTS
db.execSQL("CREATE VIRTUAL TABLE fts_table USING fts3 ( col_1, col_2, text_column )");
Ini bisa masuk ke onCreate()
metode SQLiteOpenHelper
kelas tambahan Anda .
Isi 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.')");
Akan lebih baik jika menggunakan SQLiteDatabase # insert atau prepared statement daripada execSQL
.
Tabel FTS Kueri
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_table WHERE fts_table MATCH ?", selectionArgs);
Anda juga bisa menggunakan metode kueri SQLiteDatabase # . Catat MATCH
kata kuncinya.
Jawaban Lebih Lengkap
Tabel FTS virtual di atas bermasalah. Setiap kolom diindeks, tetapi ini akan membuang-buang ruang dan sumber daya jika beberapa kolom tidak perlu diindeks. Satu-satunya kolom yang membutuhkan indeks FTS mungkin adalah text_column
.
Untuk mengatasi masalah ini kita akan menggunakan kombinasi tabel biasa dan tabel FTS virtual. Tabel FTS akan berisi indeks tetapi tidak ada data aktual dari tabel biasa. Alih-alih itu akan memiliki tautan ke konten tabel biasa. Ini disebut tabel konten eksternal .
Buat Tabel
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)");
Perhatikan bahwa kita harus menggunakan FTS4 untuk melakukan ini daripada FTS3. FTS4 tidak didukung di Android sebelum API versi 11. Anda dapat (1) hanya menyediakan fungsionalitas pencarian untuk API> = 11, atau (2) menggunakan tabel FTS3 (tetapi ini berarti database akan lebih besar karena kolom teks lengkap ada di kedua database).
Isi Tabel
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.')");
(Sekali lagi, ada cara yang lebih baik untuk memasukkan do daripada dengan execSQL
. Saya hanya menggunakannya agar mudah dibaca.)
Jika Anda mencoba melakukan query FTS sekarang, fts_example_table
Anda tidak akan mendapatkan hasil. Alasannya adalah bahwa mengubah satu tabel tidak secara otomatis mengubah tabel lainnya. Anda harus memperbarui tabel FTS secara manual:
db.execSQL("INSERT INTO fts_example_table (docid, text_column) SELECT _id, text_column FROM example_table");
(Ini docid
seperti rowid
untuk tabel biasa.) Anda harus memastikan untuk memperbarui tabel FTS (sehingga dapat memperbarui indeks) setiap kali Anda membuat perubahan (INSERT, DELETE, UPDATE) ke tabel konten eksternal. Ini bisa menjadi tidak praktis. Jika Anda hanya membuat database yang sudah diisi sebelumnya, Anda bisa melakukannya
db.execSQL("INSERT INTO fts_example_table(fts_example_table) VALUES('rebuild')");
yang akan membangun kembali seluruh tabel. Ini bisa lambat, jadi ini bukan sesuatu yang ingin Anda lakukan setelah setiap perubahan kecil. Anda akan melakukannya setelah menyelesaikan semua sisipan di tabel konten eksternal. Jika Anda memang perlu menjaga database tetap sinkron secara otomatis, Anda dapat menggunakan pemicu . Buka di sini dan gulir ke bawah sedikit untuk menemukan petunjuk arah.
Buat kueri pada Database
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_example_table WHERE fts_example_table MATCH ?", selectionArgs);
Ini sama seperti sebelumnya, kecuali kali ini Anda hanya memiliki akses ke text_column
(dan docid
). Bagaimana jika Anda perlu mendapatkan data dari kolom lain di tabel konten eksternal? Karena docid
tabel FTS cocok dengan rowid
(dan dalam kasus ini _id
) dari tabel konten eksternal, Anda dapat menggunakan gabungan. (Terima kasih atas jawaban ini untuk bantuannya.)
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);
Bacaan lebih lanjut
Bacalah dokumen-dokumen ini dengan hati-hati untuk mengetahui cara lain menggunakan tabel virtual FTS:
catatan tambahan