คำตอบพื้นฐานที่สุด
ฉันใช้ 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 # แทรกหรือเตรียมงบ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 ก่อน API เวอร์ชัน 11 คุณสามารถ (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')");
ซึ่งจะสร้างตารางใหม่ทั้งหมด สิ่งนี้อาจเป็นไปอย่างช้าๆดังนั้นจึงไม่ใช่สิ่งที่คุณต้องการทำหลังจากการเปลี่ยนแปลงเพียงเล็กน้อย คุณต้องทำหลังจากเสร็จสิ้นการแทรกทั้งหมดในตารางเนื้อหาภายนอก หากคุณไม่จำเป็นต้องเก็บฐานข้อมูลในการซิงค์โดยอัตโนมัติคุณสามารถใช้ทริกเกอร์ ไปที่นี่และเลื่อนลงเล็กน้อยเพื่อค้นหาเส้นทาง
ค้นหาฐานข้อมูล
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:
หมายเหตุเพิ่มเติม
- ผู้ประกอบการ Set (AND, OR, NOT) ในการสืบค้นข้อมูล SQLite FTS มีมาตรฐานแบบสอบถามไวยากรณ์และปรับปรุงแบบสอบถามไวยากรณ์ แต่น่าเสียดายที่ Android เห็นได้ชัดว่าไม่สนับสนุนการปรับปรุงแบบสอบถามไวยากรณ์ (ดูที่นี่ , ที่นี่ , ที่นี่และที่นี่ ) นั่นหมายความว่าการผสม AND และ OR กลายเป็นเรื่องยาก (ต้องใช้
UNION
หรือตรวจสอบPRAGMA compile_options
ดู) โชคร้ายมาก โปรดเพิ่มความคิดเห็นหากมีการอัปเดตในพื้นที่นี้