Saya kesulitan memahami cara menggunakan penelusuran teks lengkap (FTS) dengan Android. Saya telah membaca dokumentasi SQLite tentang ekstensi FTS3 dan FTS4 . Dan saya tahu itu mungkin dilakukan di Android . Namun, saya kesulitan menemukan contoh yang dapat saya pahami.
Model database dasar
Tabel database SQLite (bernama example_table
) memiliki 4 kolom. Namun, hanya ada satu kolom (bernama text_column
) yang perlu diindeks untuk pencarian teks lengkap. Setiap baris text_column
berisi teks yang panjangnya bervariasi dari 0 hingga 1000 kata. Jumlah baris lebih dari 10.000.
- Bagaimana Anda menyiapkan tabel dan / atau tabel virtual FTS?
- Bagaimana Anda akan melakukan kueri FTS
text_column
?
Catatan tambahan:
- Karena hanya satu kolom yang perlu diindeks, hanya menggunakan tabel FTS (dan menghapus
example_table
) tidak akan efisien untuk kueri non-FTS . - Untuk tabel sebesar itu, menyimpan entri duplikat
text_column
dalam tabel FTS tidak diinginkan. Posting ini menyarankan menggunakan tabel konten eksternal . - Tabel konten eksternal menggunakan FTS4, tetapi FTS4 tidak didukung sebelum Android API 11 . Sebuah jawaban dapat mengasumsikan API> = 11, tetapi mengomentari opsi untuk mendukung versi yang lebih rendah akan sangat membantu.
- Mengubah data dalam tabel asli tidak secara otomatis memperbarui tabel FTS (dan sebaliknya). Memasukkan pemicu dalam jawaban Anda tidak perlu untuk contoh dasar ini, tetapi tetap akan membantu.
android
sqlite
full-text-search
Suragch
sumber
sumber
Jawaban:
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()
metodeSQLiteOpenHelper
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
sepertirowid
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 melakukannyadb.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
(dandocid
). Bagaimana jika Anda perlu mendapatkan data dari kolom lain di tabel konten eksternal? Karenadocid
tabel FTS cocok denganrowid
(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
UNION
atau pemeriksaanPRAGMA compile_options
tampaknya). Sangat disayangkan. Silakan tambahkan komentar jika ada pembaruan di area ini.sumber
Jangan lupa saat menggunakan konten from untuk membangun kembali tabel fts.
Saya melakukan ini dengan pemicu pada pembaruan, sisipkan, hapus
sumber
INSERT INTO foo_fts VALUES("rebuild")