كيف أضفت ميزة البحث المتسامح مع الأخطاء المطبعية باستخدام OpenSearch ولغات CJK
كانت الاستعلامات التي لا تُسفر عن نتائج تقتل وقت المشاهدة لدينا.
لمدة عام، استخدم TopVideoHub تقنية SQLite FTS5 للبحث. كانت تعمل مع المطابقات الدقيقة، لكنها فشلت عندما يرتكب المستخدمون أخطاءً مطبعية.
كان الناس يبحثون عن "demon slyer" بدلاً من "demon slayer". كما كانوا يضيفون مسافات عشوائية في العناوين اليابانية أو الكورية. ولأن FTS5 يطابق الرموز (tokens) بدقة، فإن خطأً مطبعياً واحداً كان يعني عدم ظهور أي نتائج. لم يكن المستخدمون يحاولون البحث مرة أخرى، بل كانوا يغادرون ببساطة.
قمت بنقل البحث عن العناوين إلى OpenSearch. إليكم كيف قمت بحل هذه المشكلة لجمهور يتحدث لغات متعددة.
المشكلة في خاصية "الغموض" (Fuzziness) القياسية
تخبرك معظم الدروس التعليمية باستخدام خاصية "fuzziness" لإصلاح الأخطاء المطبعية. هذا يعمل مع اللغة الإنجليزية، لكنه يفشل مع النصوص الصينية واليابانية والكورية (CJK).
- مسافة التعديل (Edit distance) سيئة بالنسبة للغات CJK. فغالباً ما يعني الخطأ المطبعي في هذه اللغات استخدام حرف خاطئ تماماً.
- خاصية fuzziness القياسية تنتج نتائج غير ذات معنى (semantic garbage). فقد تطابق كلمة "fire" مع "water" لأنهما تفصل بينهما عملية تعديل واحدة.
- عملية التجزئة (Tokenization) صعبة؛ حيث لا تستخدم لغات CJK مسافات بين الكلمات.
الحل: نهج متعدد الحقول
توقفت عن معاملة جميع النصوص بنفس الطريقة. قمت بإنشاء حقل عنوان منطقي واحد يقوم بفهرسة البيانات بثلاث طرق مختلفة:
- اللاتينية والروماجي (Romaji): استخدمت التجزئة القياسية مع تفعيل خاصية fuzziness. قمت بضبط طول البادئة (prefix length) على 1، مما يضمن مطابقة "demon" مع "demn" ولكن يمنع مطابقة "lemon" مع "demon".
- نصوص CJK: استخدمت محلل CJK bigram وموحد ICU normalizer. قمت بإيقاف خاصية fuzziness، وبدلاً من ذلك، استخدمت حد أدنى للمطابقة بنسبة 70%.
- الإكمال التلقائي (Autocomplete): استخدمت حقل edge-ngram لتشغيل نتائج "البحث أثناء الكتابة" (search-as-you-type).
البنية التحتية وسلامة البيانات
احتفظت بـ SQLite كمصدر وحيد للحقيقة (single source of truth)، بينما يعمل OpenSearch كمؤشر سريع وقابل لإعادة البناء.
- أستخدم PHP لإرسال التحديثات إلى OpenSearch في دفعات كبيرة (bulk batches).
- لا أقوم أبداً بتشغيل عملية الفهرسة أثناء طلب المستخدم.
- أقوم بتشغيل سكربت Python للتحقق من وجود "انحراف" (drift)، لضمان مطابقة عدد السجلات في OpenSearch مع عددها في SQLite.
النتائج
كان التغيير هائلاً:
- انخفضت الاستعلامات التي لا تُسفر عن نتائج من 14% إلى أقل من 3%.
- أصبحت جلسات البحث أطول لأن المستخدمين وجدوا ما يريدونه على الفور.
- لا تزال سرعة الاستجابة (latency) منخفضة عند حوالي 40 مللي ثانية.
إذا كنت تستهدف جمهوراً يتحدث لغات متعددة، تذكر: التسامح مع الأخطاء المطبعية ومطابقة لغات CJK هما مشكلتان مختلفتان، وتحتاج إلى حلين مختلفين.
