איך הוספתי חיפוש עמיד לטעויות כתיב עם OpenSearch ו-CJK
שאילתות ללא תוצאות הרסו לנו את זמן הצפייה.
במשך שנה, TopVideoHub השתמש ב-SQLite FTS5 לצורך חיפוש. זה עבד עבור התאמות מדויקות, אך נכשל כאשר משתמשים ביצעו טעויות כתיב.
אנשים חיפשו "demon slyer" במקום "demon slayer". הם הוסיפו רווחים מיותרים בכותרות ביפנית או בקוריאנית. מכיוון ש-FTS5 מתאים טוקנים (tokens) מדויקים, טעות כתיב אחת גרמה לאפס תוצאות. המשתמשים לא חיפשו שוב; הם פשוט עזבו.
העברתי את חיפוש הכותרות שלנו ל-OpenSearch. הנה איך פתרתי את זה עבור קהל רב-לשוני.
הבעיה עם fuzziness סטנדרטי
רוב המדריכים יגידו לכם להשתמש ב-"fuzziness" כדי לתקן טעויות כתיב. זה עובד עבור אנגלית, אך זה נכשל בטקסט בסינית, יפנית וקוריאנית (CJK).
edit distanceאינו מתאים ל-CJK. טעות כתיב ב-CJK פירושה לעיתים קרובות שימוש בתו (character) שגוי לחלוטין.fuzzinessסטנדרטי יוצר "זבל סמנטי". הוא עלול להתאים בין "fire" ל-"water" כי הם במרחק עריכה אחד זה מזה.tokenizationהיא משימה קשה. שפות CJK אינן משתמשות ברווחים בין מילים.
הפתרון: גישת רב-שדות (Multi-Field Approach)
הפסקתי להתייחס לכל הטקסט באותו אופן. יצרתי שדה כותרת לוגי אחד המאנדקס בשלוש דרכים שונות:
- לטינית ורומאג'י (Romaji): השתמשתי ב-
tokenizationסטנדרטי עםfuzzinessמופעל. הגדרתיprefix lengthשל 1. זה מבטיח ש-"demon" יתאים ל-"demn", אך "lemon" לא יתאים ל-"demon". - טקסט CJK: השתמשתי ב-
CJK bigram analyzerוב-ICU normalizer. כיביתי את ה-fuzziness. במקום זאת, השתמשתי ב-minimum match thresholdשל 70%. - Autocomplete: השתמשתי בשדה
edge-ngramכדי להפעיל תוצאות מסוגsearch-as-you-type.
ארכיטקטורה ובטיחות נתונים
שמרתי על SQLite כ-single source of truth. OpenSearch משמש כאינדקס מהיר שניתן לבנייה מחדש.
- אני משתמש ב-PHP כדי לדחוף עדכונים ל-OpenSearch ב-
bulk batches. - אני לעולם לא מריץ
indexingבמהלך בקשת משתמש. - אני מריץ סקריפט Python כדי לבדוק "סטייה" (
drift). זה מבטיח שספירת הנתונים ב-OpenSearch תואמת לספירה ב-SQLite.
התוצאות
השינוי היה עצום:
- שאילתות ללא תוצאות ירדו מ-14% לפחות מ-3%.
- סשנים של חיפוש הפכו לארוכים יותר מכיוון שמשתמשים מצאו את מה שחיפשו באופן מיידי.
- ה-
latencyנשאר נמוך, סביב 40ms.
אם אתם משרתים קהל רב-לשוני, זכרו: עמידות לטעויות כתיב והתאמת CJK הם שני בעיות שונות. אתם זקוקים לשני פתרונות שונים.
