Android में पूर्ण पाठ खोज उदाहरण


87

मुझे एंड्रॉइड के साथ पूर्ण पाठ खोज (FTS) का उपयोग करने का एक कठिन समय समझ में आ रहा है। मैंने FTS3 और FTS4 एक्सटेंशन पर SQLite प्रलेखन पढ़ा है । और मुझे पता है कि यह एंड्रॉइड पर करना संभव है । हालाँकि, मुझे कोई भी उदाहरण मिलने में मुश्किल हो रही है जिसे मैं समझ सकता हूँ।

मूल डेटाबेस मॉडल

एक SQLite डेटाबेस तालिका (नाम example_table) में 4 कॉलम हैं। हालाँकि, केवल एक कॉलम (नाम text_column) है जिसे पूर्ण पाठ खोज के लिए अनुक्रमित करने की आवश्यकता है। text_columnपाठ की प्रत्येक पंक्ति में 0 से 1000 शब्दों की लंबाई में भिन्न पाठ होते हैं। पंक्तियों की कुल संख्या 10,000 से अधिक है।

  • आप टेबल और / या एफटीएस वर्चुअल टेबल कैसे सेट करेंगे?
  • आप एफटीएस क्वेरी पर कैसे प्रदर्शन करेंगे text_column?

अतिरिक्त नोट्स:

  • क्योंकि केवल एक कॉलम को अनुक्रमित करने की आवश्यकता है, केवल गैर-एफटीएस प्रश्नों के लिए एफटीएस तालिका (और ड्रॉपिंग example_table) का उपयोग करना अक्षम होगा ।
  • इतनी बड़ी तालिका के लिए, text_columnएफटीएस तालिका में डुप्लिकेट प्रविष्टियों को संग्रहीत करना अवांछनीय होगा। यह पोस्ट बाहरी सामग्री तालिका का उपयोग करने का सुझाव देती है ।
  • बाहरी सामग्री तालिकाएँ FTS4 का उपयोग करती हैं, लेकिन FTS4 Android API 11 से पहले समर्थित नहीं है । एक उत्तर एक एपीआई> = 11 मान सकता है, लेकिन कम संस्करणों का समर्थन करने के लिए विकल्पों पर टिप्पणी करना सहायक होगा।
  • मूल तालिका में डेटा बदलने से स्वचालित रूप से एफटीएस तालिका (और इसके विपरीत) अपडेट नहीं होती है। आपके उत्तर में ट्रिगर शामिल करना इस मूल उदाहरण के लिए आवश्यक नहीं है, लेकिन फिर भी मददगार होगा।

3
अच्छी तरह से प्रलेखित प्रश्न, मैं यहाँ मिली मनमानी का प्रतिकार कर रहा हूँ।
मेकप

जवाबों:


117

सबसे बुनियादी जवाब

मैं नीचे दिए गए सादे वर्ग का उपयोग कर रहा हूं ताकि सब कुछ यथासंभव स्पष्ट और पठनीय हो। अपने प्रोजेक्ट में आप Android सुविधा विधियों का उपयोग कर सकते हैं। dbनीचे इस्तेमाल किया वस्तु का एक उदाहरण है SQLiteDatabase

एफटीएस टेबल बनाएं

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 # query विधि का उपयोग भी कर सकते हैं । MATCHकीवर्ड नोट करें ।

फुलर उत्तर

वर्चुअल FTS टेबल के साथ एक समस्या है। प्रत्येक कॉलम को अनुक्रमित किया जाता है, लेकिन यह स्थान और संसाधनों की बर्बादी है अगर कुछ कॉलमों को अनुक्रमित करने की आवश्यकता नहीं है। एकमात्र स्तंभ जिसे एफटीएस इंडेक्स की आवश्यकता होती है वह शायद है text_column

इस समस्या को हल करने के लिए हम एक नियमित तालिका और एक आभासी 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)");

ध्यान दें कि हमें FTS3 के बजाय ऐसा करने के लिए FTS4 का उपयोग करना होगा। एफटीएस 4 को एपीआई संस्करण 11 से पहले एंड्रॉइड में समर्थित नहीं है। आप या तो (1) केवल एपीआई> = 11 के लिए खोज कार्यक्षमता प्रदान कर सकते हैं, या (2) एफटीएस 3 तालिका का उपयोग कर सकते हैं (लेकिन इसका मतलब है कि डेटाबेस बड़ा होगा क्योंकि पूर्ण पाठ कॉलम मौजूद है दोनों डेटाबेस में)।

तालिकाओं को आबाद करें

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आपको कोई परिणाम नहीं मिलेगा। कारण यह है कि एक तालिका को बदलने से स्वचालित रूप से दूसरी तालिका नहीं बदल जाती है। आपको एफटीएस तालिका को मैन्युअल रूप से अपडेट करना होगा:

db.execSQL("INSERT INTO fts_example_table (docid, text_column) SELECT _id, text_column FROM example_table");

( एक रेगुलर टेबल docidके rowidलिए जैसा है ।) आपको हर बार एफटीएस टेबल (ताकि यह इंडेक्स को अपडेट कर सके) को बाहरी सामग्री तालिका में बदलाव (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एफटीएस तालिका बाहरी सामग्री तालिका के 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 वर्चुअल टेबल का उपयोग करने के अन्य तरीकों को देखने के लिए इन दस्तावेजों को ध्यान से देखें:

अतिरिक्त नोट्स


1
वास्तव में, यदि आप जिस तरीके से निर्दिष्ट करते हैं, उसमें fts टेबल का उपयोग कर रहे हैं (गैर-एफटीएस तालिका से जहां _id fts तालिका मिलान द्वारा लौटाए गए डॉकिड के सेट में समाहित है) का उपयोग कर रहे हैं, तो आप सामग्री = "का उपयोग करके स्थान बचा सकते हैं।" । यह सामग्री की नकल के बिना पूर्ण पाठ सूचकांक बनाएगा। कंटेंटलेस FTS4 टेबल्स
astyanaxas

FTS4 सामग्री विकल्प SQLite 3.7.9 ( sqlite.org/releaselog/3_7_11.html ) की तुलना में पहले नहीं जोड़ा गया था , जिसका अर्थ है कि यह Android API 16 से पहले अनुपलब्ध है। SQLiteDatabase उपयोग प्रयास पर फेंक देगा।
नॉकल्स

इस क्वेरी के माध्यम से मुझे आधा शब्द मिलान कैसे मिलेगा?
हितेश दानीधरिया

@HiteshDanidhariya, क्या यह आंशिक शब्द मिलान नहीं है? क्षमा करें, मुझे इस पर काम करते हुए कुछ समय हो गया है, लेकिन मुझे लगा कि यह पहले ही कर चुका हूँ।
सुरगाच

@suragch ने समाधान ढूंढ लिया। सर्च एड्रिंग और थैंक्स के बाद "*" जोड़ने के लिए। आपके जवाब ने मुझे बहुत मदद की। :)
हितेश दानीधरिया

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.