मी OpenSearch आणि CJK वापरून Typo-Tolerant सर्च कसे जोडले
शून्य-निकाल (Zero-result) असलेल्या क्वेरीजमुळे आमचा वॉच टाइम (watch time) कमी होत होता.
वर्षभर, TopVideoHub ने सर्चसाठी SQLite FTS5 वापरले. ते अचूक मॅचेससाठी (exact matches) चांगले काम करत होते. परंतु, जेव्हा वापरकर्त्यांकडून स्पेलिंगमध्ये चुका (typos) होत, तेव्हा ते अपयशी ठरत असे.
लोक "demon slayer" ऐवजी "demon slyer" असे शोधत असत. जपानी किंवा कोरियन शीर्षकांमध्ये ते विनाकारण स्पेस टाकत असत. FTS5 फक्त अचूक टोकन्स (tokens) मॅच करत असल्याने, एका लहान चुकीमुळेही शून्य निकाल मिळत असत. वापरकर्ते पुन्हा शोधत नसत, ते फक्त साइट सोडून जात.
मी आमचे टायटल सर्च OpenSearch वर हलवले. बहुभाषिक प्रेक्षकांसाठी मी हे कसे सोडवले, ते खाली दिले आहे.
The Problem With Standard Fuzziness
बहुतेक ट्युटोरियल्स स्पेलिंगच्या चुका सुधारण्यासाठी "fuzziness" वापरण्याचा सल्ला देतात. हे इंग्रजीसाठी काम करते, परंतु चिनी, जपानी आणि कोरियन (CJK) मजकुरासाठी ते अपयशी ठरते.
- CJK साठी 'Edit distance' योग्य नाही. CJK मध्ये स्पेलिंगची चूक म्हणजे अनेकदा पूर्णपणे चुकीचे अक्षर वापरणे असा होतो.
- स्टँडर्ड फझिनेसमुळे अर्थहीन (semantic garbage) निकाल मिळू शकतात. उदाहरणार्थ, "fire" आणि "water" यांच्यात फक्त एक बदल (edit) असल्याने ते मॅच होऊ शकतात.
- टोकनायझेशन (Tokenization) कठीण असते. CJK भाषांमध्ये शब्दांमध्ये स्पेस वापरली जात नाही.
The Solution: A Multi-Field Approach
मी सर्व मजकुराकडे एकसारखे पाहणे थांबवले. मी एक लॉजिकल टायटल फील्ड तयार केले जे तीन वेगवेगळ्या प्रकारे इंडेक्स करते:
- Latin आणि Romaji: मी फझिनेस सक्षम (enabled) करून स्टँडर्ड टोकनायझेशन वापरले. मी 'prefix length' १ सेट केली. यामुळे "demon" हे "demn" शी मॅच होईल, पण "lemon" हे "demon" शी मॅच होणार नाही.
- CJK Text: मी CJK bigram analyzer आणि ICU normalizer वापरले. मी फझिनेस 'OFF' केले. त्याऐवजी, मी ७०% चा 'minimum match threshold' वापरला.
- Autocomplete: 'search-as-you-type' रिझल्ट्ससाठी मी edge-ngram फील्ड वापरले.
Architecture and Data Safety
मी SQLite ला 'single source of truth' म्हणून ठेवले. OpenSearch एका वेगवान आणि पुन्हा तयार करण्यायोग्य (rebuildable) इंडेक्स म्हणून काम करते.
- मी OpenSearch मध्ये बल्क बॅचेसमध्ये (bulk batches) अपडेट्स पाठवण्यासाठी PHP वापरतो.
- मी युजरच्या रिक्वेस्ट दरम्यान इंडेक्सिंग कधीही करत नाही.
- मी "drift" तपासण्यासाठी एक Python स्क्रिप्ट चालवतो. यामुळे OpenSearch मधील संख्या आणि SQLite मधील संख्या सारखीच असल्याची खात्री होते.
The Results
हा बदल खूप मोठा होता:
- शून्य-निकाल असलेल्या क्वेरीज १४% वरून ३% च्या खाली आल्या.
- सर्च सेशन्सची लांबी वाढली कारण वापरकर्त्यांना हवे असलेले साहित्य लगेच मिळाले.
- लॅटन्सी (Latency) ४०ms च्या आसपास कमी राहिली आहे.
जर तुम्ही बहुभाषिक प्रेक्षकांसाठी सेवा देत असाल, तर लक्षात ठेवा: typo tolerance आणि CJK matching या दोन वेगवेगळ्या समस्या आहेत. तुम्हाला दोन वेगवेगळ्या उपायांची गरज आहे.
