brief: | i18n.site अब सर्वर रहित पूर्ण-पाठ खोज का समर्थन करता है।
यह आलेख शुद्ध फ्रंट-एंड पूर्ण-पाठ खोज तकनीक के कार्यान्वयन का परिचय देता है, जिसमें IndexedDB द्वारा निर्मित उलटा सूचकांक, उपसर्ग खोज, शब्द विभाजन अनुकूलन और बहु-भाषा समर्थन शामिल है।
मौजूदा समाधानों की तुलना में, i18n.site की शुद्ध फ्रंट-एंड पूर्ण-पाठ खोज आकार में छोटी और तेज़ है, जो दस्तावेज़ों और ब्लॉगों जैसी छोटी और मध्यम आकार की वेबसाइटों के लिए उपयुक्त है, और ऑफ़लाइन उपलब्ध है।
कई हफ्तों के विकास के बाद, i18n.site (एक पूरी तरह से स्थिर markdown बहुभाषी अनुवाद & वेबसाइट निर्माण उपकरण) अब शुद्ध फ्रंट-एंड पूर्ण-पाठ खोज का समर्थन करता है।
यह आलेख खोज प्रभाव का अनुभव करने के लिए i18n.site
शुद्ध फ्रंट-एंड पूर्ण-पाठ खोज के तकनीकी कार्यान्वयन को साझा करेगा i18n.site
कोड खुला स्रोत : खोज कर्नेल / इंटरैक्टिव इंटरफ़ेस
दस्तावेज़/व्यक्तिगत ब्लॉग जैसी छोटी और मध्यम आकार की पूरी तरह से स्थिर वेबसाइटों के लिए, स्व-निर्मित पूर्ण-पाठ खोज बैकएंड बनाना बहुत भारी है, और सेवा-मुक्त पूर्ण-पाठ खोज अधिक सामान्य विकल्प है।
सर्वर रहित पूर्ण-पाठ खोज समाधान दो व्यापक श्रेणियों में आते हैं:
सबसे पहले, समान algolia.com तृतीय-पक्ष खोज सेवा प्रदाता पूर्ण-पाठ खोज के लिए फ्रंट-एंड घटक प्रदान करते हैं।
ऐसी सेवाओं के लिए खोज मात्रा के आधार पर भुगतान की आवश्यकता होती है, और वेबसाइट अनुपालन जैसे मुद्दों के कारण अक्सर मुख्य भूमि चीन में उपयोगकर्ताओं के लिए उपलब्ध नहीं होती हैं।
इसे ऑफ़लाइन उपयोग नहीं किया जा सकता, इंट्रानेट पर उपयोग नहीं किया जा सकता और इसकी बड़ी सीमाएँ हैं। इस लेख में ज्यादा चर्चा नहीं है.
दूसरा शुद्ध फ्रंट-एंड पूर्ण-पाठ खोज है।
वर्तमान में, सामान्य शुद्ध फ्रंट-एंड पूर्ण-पाठ खोजों में lunrjs और ElasticLunr.js ( lunrjs
माध्यमिक विकास पर आधारित) शामिल हैं।
lunrjs
इंडेक्स बनाने के दो तरीके हैं और दोनों की अपनी-अपनी समस्याएं हैं।
पूर्व-निर्मित अनुक्रमणिका फ़ाइलें
चूँकि सूचकांक में सभी दस्तावेज़ों के शब्द शामिल हैं, इसलिए इसका आकार बड़ा है। जब भी कोई दस्तावेज़ जोड़ा या संशोधित किया जाता है, तो एक नई इंडेक्स फ़ाइल लोड की जानी चाहिए। इससे उपयोगकर्ता का प्रतीक्षा समय बढ़ जाएगा और बहुत अधिक बैंडविड्थ की खपत होगी।
दस्तावेज़ लोड करें और तुरंत अनुक्रमणिका बनाएं
एक इंडेक्स बनाना एक कम्प्यूटेशनल रूप से गहन कार्य है। हर बार जब आप इसे एक्सेस करते हैं तो इंडेक्स का पुनर्निर्माण करना स्पष्ट अंतराल और खराब उपयोगकर्ता अनुभव का कारण बनेगा।
lunrjs
के अलावा, कुछ अन्य पूर्ण-पाठ खोज समाधान भी हैं, जैसे :
fusejs , खोजने के लिए स्ट्रिंग्स के बीच समानता की गणना करें।
इस समाधान का प्रदर्शन बेहद खराब है और इसका उपयोग पूर्ण-पाठ खोज के लिए नहीं किया जा सकता है (देखें Fuse.js लंबी क्वेरी में 10 सेकंड से अधिक समय लगता है, इसे कैसे अनुकूलित करें? )।
TinySearch , खोजने के लिए ब्लूम फ़िल्टर का उपयोग करें, उपसर्ग खोज के लिए उपयोग नहीं किया जा सकता है (उदाहरण के लिए, goo
दर्ज करें, good
खोजें, google
), और समान स्वचालित पूर्णता प्रभाव प्राप्त नहीं कर सकता है।
मौजूदा समाधानों की कमियों के कारण, i18n.site
एक नया शुद्ध फ्रंट-एंड पूर्ण-पाठ खोज समाधान विकसित किया, जिसमें निम्नलिखित विशेषताएं हैं :
gzip
के बाद खोज कर्नेल का आकार 6.9KB
है (तुलना के लिए, lunrjs
का आकार 25KB
है)indexedb
पर आधारित एक उलटा इंडेक्स बनाएं, जो कम मेमोरी लेता है और तेज़ है।नीचे, 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()
में:
/\p{P}/
एक नियमित अभिव्यक्ति है जो विराम चिह्नों से मेल खाती है। विशिष्ट मिलान प्रतीकों में शामिल हैं: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _
{ | } ~. .</p><ul><li>
split('.')इसलिए है क्योंकि
Firefoxब्राउज़र शब्द विभाजन
. ` को खंडित नहीं करता है।
IndexedDB
में 5 ऑब्जेक्ट स्टोरेज टेबल बनाए गए :
word
: id - शब्दdoc
: id - दस्तावेज़ url - दस्तावेज़ संस्करण संख्याdocWord
: दस्तावेज़ की सारणी id - शब्द idprefix
: उपसर्ग - शब्द id की सारणीrindex
: शब्द id - दस्तावेज़ id : पंक्ति संख्याओं की सारणीदस्तावेज़ url
और संस्करण संख्या ver
की सरणी में पास करें, और खोजें कि दस्तावेज़ तालिका doc
में मौजूद है या नहीं। यदि यह मौजूद नहीं है, तो एक उलटा सूचकांक बनाएं। साथ ही, उन दस्तावेज़ों के लिए उलटा सूचकांक हटा दें जिन्हें पारित नहीं किया गया था।
इस तरह, वृद्धिशील अनुक्रमण प्राप्त किया जा सकता है और गणना की मात्रा कम हो जाती है।
फ्रंट-एंड इंटरेक्शन में, पहली बार लोड करते समय अंतराल से बचने के लिए इंडेक्स की लोडिंग प्रोग्रेस बार प्रदर्शित की जा सकती है। देखें "एनीमेशन के साथ प्रोग्रेस बार, सिंगल पर आधारित progress + शुद्ध css कार्यान्वयन" अंग्रेजी / चीनी ।
प्रोजेक्ट को अतुल्यकालिक एनकैप्सुलेशन के आधार पर 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
ओपन सोर्स स्व-विकसित शुद्ध फ्रंट-एंड खोज, आकार में छोटा और तेज़ प्रतिक्रिया, वर्तमान शुद्ध फ्रंट-एंड पूर्ण-पाठ खोज की कमियों को हल करता है और एक बेहतर उपयोगकर्ता अनुभव प्रदान करता है।