brief: | يدعم موقع i18n.site الآن البحث عن النص الكامل بدون خادم.

تقدم هذه المقالة تطبيق تقنية البحث عن النص الكامل للواجهة الأمامية، بما في ذلك الفهرس المقلوب الذي تم إنشاؤه بواسطة IndexedDB، والبحث عن البادئات، وتحسين تجزئة الكلمات، والدعم متعدد اللغات.

بالمقارنة مع الحلول الحالية، فإن البحث عن النص الكامل للواجهة الأمامية النقية لـ i18n.site صغير الحجم وسريع، ومناسب لمواقع الويب الصغيرة والمتوسطة الحجم مثل المستندات والمدونات، ومتاح دون اتصال بالإنترنت.


البحث عن النص الكامل المقلوب للواجهة الأمامية النقية

تسلسل

بعد عدة أسابيع من التطوير، i18n.site (أداة إنشاء موقع ويب ثابتة تمامًا markdown multilingualtranslation & ) تدعم الآن البحث عن النص الكامل في الواجهة الأمامية.

ستشارك هذه المقالة التنفيذ الفني لبحث النص الكامل للواجهة الأمامية 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 إذا لم يكن موجودًا، فقم بإنشاء فهرس مقلوب. وفي الوقت نفسه، قم بإزالة الفهرس المقلوب لتلك المستندات التي لم يتم تمريرها.

بهذه الطريقة، يمكن تحقيق الفهرسة المتزايدة وتقليل مقدار الحساب.

في التفاعل الأمامي، يمكن عرض شريط تقدم التحميل الخاص بالفهرس لتجنب التأخير عند التحميل لأول مرة، راجع "شريط التقدم مع الرسوم المتحركة، بناءً على تطبيق واحد progress + Pure css " الإنجليزية / الصينية.

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 كلمة بعد تجزئة الكلمة، عند إرجاع النتائج، سيتم إرجاع النتائج التي تحتوي على جميع الكلمات الرئيسية أولاً، ثم سيتم إرجاع النتائج التي تحتوي على N-1، N-2،...، 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 بحث أمامي نقي مفتوح المصدر تم تطويره ذاتيًا، صغير الحجم وسريع الاستجابة، يحل عيوب البحث عن النص الكامل الحالي للواجهة الأمامية النقية ويوفر تجربة مستخدم أفضل.