چگونه جستجوی مقاوم در برابر غلط املایی را با OpenSearch و CJK اضافه کردم
پرسوجوهای بدون نتیجه، زمان تماشای ما را از بین میبردند.
به مدت یک سال، TopVideoHub از SQLite FTS5 برای جستجو استفاده میکرد. این روش برای تطبیقهای دقیق (exact matches) خوب کار میکرد، اما وقتی کاربران غلط املایی داشتند، شکست میخورد.
مردم به جای "demon slayer"، عبارت "demon slyer" را جستجو میکردند. یا در عناوین ژاپنی یا کرهای، فاصلههای اضافی اضافه میکردند. از آنجایی که FTS5 با توکنهای دقیق مطابقت دارد، یک غلط املایی ساده به معنای صفر نتیجه بود. کاربران دوباره جستجو نمیکردند؛ آنها فقط سایت را ترک میکردند.
من جستجوی عناوین را به OpenSearch منتقل کردم. در اینجا توضیح میدهم که چگونه این مشکل را برای مخاطبان چندزبانه حل کردم.
مشکل با Fuzziness استاندارد
بیشتر آموزشها به شما میگویند که برای رفع غلطهای املایی از "fuzziness" استفاده کنید. این روش برای انگلیسی جواب میدهد، اما برای متنهای چینی، ژاپنی و کرهای (CJK) شکست میخورد.
- فاصله ویرایشی (Edit distance) برای CJK مناسب نیست. یک غلط املایی در CJK اغلب به معنای استفاده از یک کاراکتر کاملاً متفاوت است.
- fuzziness استاندارد باعث ایجاد زبالههای معنایی (semantic garbage) میشود. ممکن است کلمه "fire" را با "water" مطابقت دهد، چون تنها یک ویرایش با هم فاصله دارند.
- توکنسازی (Tokenization) دشوار است. زبانهای CJK از فاصله بین کلمات استفاده نمیکنند.
راه حل: رویکرد چند-فیلدی (Multi-Field Approach)
من دیگر با همه متنها به یک شکل برخورد نکردم. یک فیلد منطقی برای عنوان ایجاد کردم که به سه روش مختلف ایندکس میشود:
- Latin and Romaji: از توکنسازی استاندارد با قابلیت fuzziness فعال استفاده کردم. طول پیشوند (prefix length) را روی ۱ تنظیم کردم. این کار تضمین میکند که "demon" با "demn" مطابقت داشته باشد، اما "lemon" با "demon" مطابقت نداشته باشد.
- CJK Text: از یک CJK bigram analyzer و یک ICU normalizer استفاده کردم. قابلیت fuzziness را خاموش کردم. در عوض، از آستانه حداقل تطبیق (minimum match threshold) ۷۰٪ استفاده کردم.
- Autocomplete: از یک فیلد edge-ngram برای ارائه نتایج "جستجو هنگام تایپ" (search-as-you-type) استفاده کردم.
معماری و امنیت دادهها
من SQLite را به عنوان تنها منبع حقیقت (single source of truth) نگه داشتم. OpenSearch به عنوان یک ایندکس سریع و قابل بازسازی عمل میکند.
- من از PHP برای ارسال بهروزرسانیها به OpenSearch در دستههای بزرگ (bulk batches) استفاده میکنم.
- من هرگز فرآیند ایندکسگذاری را در حین درخواست کاربر اجرا نمیکنم.
- من یک اسکریپت Python برای بررسی "انحراف" (drift) اجرا میکنم. این کار تضمین میکند که تعداد رکوردها در OpenSearch با تعداد در SQLite مطابقت داشته باشد.
نتایج
تغییرات بسیار بزرگ بود:
- پرسوجوهای بدون نتیجه از ۱۴٪ به زیر ۳٪ کاهش یافت.
- جلسات جستجو طولانیتر شدند زیرا کاربران بلافاصله آنچه را که میخواستند پیدا میکردند.
- تأخیر (Latency) در حدود ۴۰ میلیثانیه پایین باقی مانده است.
اگر به مخاطبان چندزبانه خدمات میدهید، به یاد داشته باشید: مقاومت در برابر غلط املایی و تطبیق CJK دو مشکل متفاوت هستند. شما به دو راه حل متفاوت نیاز دارید.
