最基本的答案
我用下面讓一切都清晰可讀儘可能普通的SQL。在您的項目中,您可以使用Android便捷方法。下面使用的db
對象是SQLiteDatabase的實例。
Create FTS Table
db.execSQL("CREATE VIRTUAL TABLE fts_table USING fts3 (col_1, col_2, text_column)");
這可以去你的外擴SQLiteOpenHelper
類的onCreate()
方法。
Populate FTS Table
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或prepared statements比execSQL
。
Query FTS Table
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_table WHERE fts_table MATCH ?", selectionArgs);
您也可以使用SQLiteDatabase#query方法。請注意0關鍵字。
Fuller答案
上面的虛擬FTS表有一個問題。每列都被編入索引,但如果某些列不需要編制索引,則這會浪費空間和資源。唯一需要FTS指數的列可能是text_column
。
要解決這個問題,我們將使用常規表和虛擬FTS表的組合。 FTS表將包含索引,但不包含常規表中的實際數據。相反,它將鏈接到常規表格的內容。這被稱爲external content table。
創建表
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。在API版本11之前,Android不支持FTS4。您可以(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.')");
(同樣,也有更好的方式執行插入比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')");
這將重建整個表。但是,這可能會很慢,所以在每次小改動之後,這都不是你想要做的。在完成外部內容表中的所有插入之後,您可以執行此操作。如果您確實需要自動同步數據庫,則可以使用triggers。 Go here並向下滾動以查找路線。
查詢的數據庫
String[] selectionArgs = { searchString };
Cursor cursor = db.rawQuery("SELECT * FROM fts_example_table WHERE fts_example_table MATCH ?", selectionArgs);
這是和以前一樣,但這個時候你只能訪問text_column
(和docid
)。如果您需要從外部內容表中的其他列中獲取數據,該怎麼辦?由於FTS表的docid
與外部內容表的rowid
(在此例中爲_id
)匹配,因此可以使用聯接。 (感謝this answer尋求幫助。)
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虛擬表的其他方式:
附加說明
證據充分的問題,我對付你來到這裏任意downvote。 – Mekap