brief: | i18n.site תומך כעת בחיפוש טקסט מלא ללא שרת.

מאמר זה מציג את הטמעת טכנולוגיית חיפוש טקסט מלא חזיתית, כולל אינדקס הפוך שנבנה על ידי IndexedDB, חיפוש קידומת, אופטימיזציה של פילוח מילים ותמיכה בריבוי שפות.

בהשוואה לפתרונות קיימים, החיפוש הטהור של i18n.site בטקסט מלא הוא קטן בגודלו ומהיר, מתאים לאתרי אינטרנט קטנים ובינוניים כגון מסמכים ובלוגים, וזמין במצב לא מקוון.


חיפוש הפוך טהור בטקסט מלא

רֶצֶף

לאחר מספר שבועות של פיתוח, i18n.site (כלי לבניית & markdown רב לשוני גרידא) תומך בחיפוש טהור בטקסט מלא.

מאמר זה ישתף את ההטמעה הטכנית של i18n.site חיפוש בטקסט מלא. בקר i18n.site

קוד קוד : חפש ממשק / אינטראקטיבי

סקירה כללית של פתרונות חיפוש בטקסט מלא ללא שרת

עבור אתרים קטנים ובינוניים סטטיים גרידא כגון מסמכים/בלוגים אישיים, בניית קצה עורפי לחיפוש בטקסט מלא בנוי בעצמו היא כבדה מדי, וחיפוש טקסט מלא ללא שירות הוא הבחירה הנפוצה יותר.

פתרונות חיפוש בטקסט מלא ללא שרת מתחלקים לשתי קטגוריות רחבות:

ראשית, ספקי שירותי חיפוש של צד שלישי algolia.com מספקים רכיבי קצה לחיפוש בטקסט מלא.

שירותים כאלה דורשים תשלום על סמך נפח החיפוש, ולעתים קרובות אינם זמינים למשתמשים בסין היבשתית עקב בעיות כגון תאימות לאתרים.

לא ניתן להשתמש בו במצב לא מקוון, לא ניתן להשתמש בו באינטראנט, ויש לו מגבלות גדולות. מאמר זה אינו דן הרבה.

השני הוא חיפוש טקסט מלא בחזית הקצה.

נכון לעכשיו, חיפושי טקסט מלא נפוצים בחזית כוללים lunrjs ו- ElasticLunr.js (מבוסס על lunrjs פיתוח משני).

lunrjs ישנן שתי דרכים לבנות אינדקסים, ולשתיהן יש בעיות משלהן.

  1. קבצי אינדקס בנויים מראש

    מכיוון שהאינדקס מכיל מילים מכל המסמכים, הוא גדול בגודלו. בכל פעם שמסמך מתווסף או משנה, יש לטעון קובץ אינדקס חדש. זה יגדיל את זמן ההמתנה של המשתמש ויצרוך הרבה רוחב פס.

  2. טען מסמכים ובנה אינדקסים תוך כדי תנועה

    בניית אינדקס היא משימה אינטנסיבית מבחינה חישובית בנייה מחדש של האינדקס בכל פעם שאתה ניגש אליו יגרום לפיגורים ברורים וחווית משתמש גרועה.


בנוסף ל lunrjs , ישנם עוד כמה פתרונות חיפוש בטקסט מלא, כגון :

fusejs חשב את הדמיון בין מחרוזות לחיפוש.

הביצועים של פתרון זה גרועים ביותר ולא ניתן להשתמש בהם לחיפוש בטקסט מלא (ראה Fuse.js שאילתה ארוכה נמשכת יותר מ- 10 שניות, איך מייעלים אותה? ).

TinySearch השתמש במסנן Bloom לחיפוש, לא ניתן להשתמש בו לחיפוש קידומת (לדוגמה, הזן goo , חפש good , google ), ואינו יכול להשיג אפקט השלמה אוטומטי דומה.

בגלל החסרונות של הפתרונות הקיימים, i18n.site פיתחה פתרון חדש לחיפוש טקסט מלא פרונט-אנד טהור, בעל המאפיינים הבאים :

  1. תומך בחיפוש מרובה שפות והוא קטן בגודלו גודל ליבת החיפוש לאחר אריזה gzip הוא 6.9KB (לשם השוואה, הגודל של lunrjs הוא 25KB ).
  2. בנה אינדקס הפוך על בסיס indexedb , שתופס פחות זיכרון ומהיר.
  3. כאשר מסמכים מתווספים/משונים, רק המסמכים שנוספו או השתנו עוברים לאינדקס מחדש, מה שמפחית את כמות החישובים.
  4. תומך בחיפוש קידומת, שיכול להציג תוצאות חיפוש בזמן אמת בזמן שהמשתמש מקליד.
  5. זמין במצב לא מקוון

להלן, i18n.site פרטי יישום טכניים יוצגו בפירוט.

פילוח מילים רב לשוני

פילוח מילים משתמש בפילוח המילים המקורי של הדפדפן Intl.Segmenter , וכל הדפדפנים המיינסטרים תומכים בממשק זה.

קוד המילה פילוח coffeescript הוא כדלקמן

SEG = new Intl.Segmenter 0, granularity: "word"

seg = (txt) =>
  r = []
  for {segment} from SEG.segment(txt)
    for i from segment.split('.')
      i = i.trim()
      if i and !'|`'.includes(i) and !/\p{P}/u.test(i)
        r.push i
  r

export default seg

export segqy = (q) =>
  seg q.toLocaleLowerCase()

ב:

בניית אינדקס

5 טבלאות אחסון חפצים נוצרו ב IndexedDB :

עברו במערך של מסמך url וגרסה מספר ver , וחפשו האם המסמך קיים בטבלה doc אם הוא לא קיים, צור אינדקס הפוך. במקביל, הסר את האינדקס ההפוך עבור אותם מסמכים שלא הועברו.

בדרך זו ניתן להגיע לאינדקס מצטבר ולצמצם את כמות החישוב.

באינטראקציה קדמית, ניתן להציג את סרגל התקדמות הטעינה של האינדקס / להימנע מהפיגור בעת css בפעם progress + .

IndexedDB כתיבה בו זמנית גבוהה

הפרויקט idb על בסיס אנקפסולציה אסינכרונית של IndexedDB

הקריאה והכתיבה של IndexedDB הן אסינכרוניות. בעת יצירת אינדקס, מסמכים ייטענו במקביל ליצירת האינדקס.

על מנת למנוע אובדן נתונים חלקי שנגרם על ידי כתיבה תחרותית, אתה יכול להתייחס לקוד coffeescript למטה ולהוסיף מטמון ing בין קריאה לכתיבה כדי ליירט כתיבה מתחרה.

pusher = =>
  ing = new Map()
  (table, id, val)=>
    id_set = ing.get(id)
    if id_set
      id_set.add val
      return

    id_set = new Set([val])
    ing.set id, id_set
    pre = await table.get(id)
    li = pre?.li or []

    loop
      to_add = [...id_set]
      li.push(...to_add)
      await table.put({id,li})
      for i from to_add
        id_set.delete i
      if not id_set.size
        ing.delete id
        break
    return

rindexPush = pusher()
prefixPush = pusher()

דיוק וריקול

החיפוש יפלח תחילה את מילות המפתח שהזין המשתמש.

N-2 N-1 N מילים אחרי פילוח המילה 1

תוצאות החיפוש המוצגות תחילה מבטיחות את דיוק השאילתה, והתוצאות שנטענו לאחר מכן (לחץ על כפתור הטען עוד) מבטיחות את שיעור ההיזכרות.

טעינה לפי דרישה

על מנת לשפר את מהירות התגובה, החיפוש משתמש במחולל yield כדי ליישם טעינה לפי דרישה, וחוזר limit פעם שנשאלת שאילתה לתוצאה.

שים לב שבכל פעם שאתה מחפש שוב אחרי yield , אתה צריך לפתוח מחדש עסקת שאילתה של IndexedDB .

קידומת חיפוש בזמן אמת

על מנת להציג תוצאות חיפוש בזמן שהמשתמש מקליד, למשל, בהזנת wor , מוצגות מילים עם קידומת wor כגון words ו work .

ליבת החיפוש תשתמש בטבלת prefix עבור המילה האחרונה לאחר פילוח מילים כדי למצוא את כל המילים עם הקדמת שלה, ולחפש ברצף.

פונקציית אנטי-טלטול debounce משמשת גם באינטראקציה חזיתית (מיושם באופן הבא) כדי להפחית את תדירות קלט המשתמש המפעיל חיפושים ולהפחית את כמות החישובים.

export default (wait, func) => {
  var timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(func.bind(this, ...args), wait);
  };
}

זמין במצב לא מקוון

טבלת האינדקס אינה מאחסנת את הטקסט המקורי, אלא רק את המילים, מה שמפחית את כמות האחסון.

הדגשת תוצאות החיפוש מחייבת טעינה מחדש של הטקסט המקורי, והתאמה service worker יכולה למנוע בקשות רשת חוזרות ונשנות.

יחד עם זאת, מכיוון ש service worker מאחסן את כל המאמרים במטמון, ברגע שהמשתמש מבצע חיפוש, האתר כולו, כולל החיפוש, זמין במצב לא מקוון.

אופטימיזציה לתצוגה של מסמכי MarkDown

פתרון החיפוש החזיתי הטהור של i18n.site מותאם ל MarkDown מסמכים.

בעת הצגת תוצאות החיפוש, שם הפרק יוצג והפרק ינווט בלחיצה.

לְסַכֵּם

חיפוש הפוך בטקסט מלא מיושם אך ורק בחזית הקצה, ללא צורך בשרת. הוא מתאים מאוד לאתרים קטנים ובינוניים כמו מסמכים ובלוגים אישיים.

i18n.site חיפוש חזיתי טהור בפיתוח עצמי של קוד פתוח, קטן בגודלו ותגובה מהירה, פותר את החסרונות של החיפוש הנוכחי בטקסט מלא בחזית הקצה הטהור ומספק חווית משתמש טובה יותר.