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 , खोजने के लिए ब्लूम फ़िल्टर का उपयोग करें, उपसर्ग खोज के लिए उपयोग नहीं किया जा सकता है (उदाहरण के लिए, 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()

में:

सूचकांक निर्माण

IndexedDB में 5 ऑब्जेक्ट स्टोरेज टेबल बनाए गए :

दस्तावेज़ url और संस्करण संख्या ver की सरणी में पास करें, और खोजें कि दस्तावेज़ तालिका doc में मौजूद है या नहीं। यदि यह मौजूद नहीं है, तो एक उलटा सूचकांक बनाएं। साथ ही, उन दस्तावेज़ों के लिए उलटा सूचकांक हटा दें जिन्हें पारित नहीं किया गया था।

इस तरह, वृद्धिशील अनुक्रमण प्राप्त किया जा सकता है और गणना की मात्रा कम हो जाती है।

फ्रंट-एंड इंटरेक्शन में, पहली बार लोड करते समय अंतराल से बचने के लिए इंडेक्स की लोडिंग प्रोग्रेस बार प्रदर्शित की जा सकती है। देखें "एनीमेशन के साथ प्रोग्रेस बार, सिंगल पर आधारित progress + शुद्ध 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 सभी लेखों को कैश करता है, एक बार जब उपयोगकर्ता खोज करता है, तो खोज सहित पूरी वेबसाइट ऑफ़लाइन उपलब्ध होती है।

मार्कडाउन दस्तावेज़ों का प्रदर्शन अनुकूलन

i18n.site का शुद्ध फ्रंट-एंड खोज समाधान MarkDown दस्तावेज़ों के लिए अनुकूलित है।

खोज परिणाम प्रदर्शित करते समय, अध्याय का नाम प्रदर्शित किया जाएगा और क्लिक करने पर अध्याय नेविगेट किया जाएगा।

संक्षेप करें

उलटा पूर्ण-पाठ खोज पूरी तरह से फ्रंट एंड पर लागू की गई है, किसी सर्वर की आवश्यकता नहीं है। यह दस्तावेज़ों और व्यक्तिगत ब्लॉग जैसी छोटी और मध्यम आकार की वेबसाइटों के लिए बहुत उपयुक्त है।

i18n.site ओपन सोर्स स्व-विकसित शुद्ध फ्रंट-एंड खोज, आकार में छोटा और तेज़ प्रतिक्रिया, वर्तमान शुद्ध फ्रंट-एंड पूर्ण-पाठ खोज की कमियों को हल करता है और एक बेहतर उपयोगकर्ता अनुभव प्रदान करता है।