brief: | i18n.site сега поддржува пребарување на целосен текст без сервер.
Оваа статија воведува имплементација на чиста технологија за пребарување на целосен текст од предниот дел, вклучително и превртен индекс изграден од IndexedDB, пребарување на префикс, оптимизација на сегментација на зборови и поддршка за повеќе јазици.
Во споредба со постоечките решенија, чистото пребарување на целосен текст на предниот дел на i18n.site е мало и брзо, погодно за мали и средни веб-локации како што се документи и блогови и е достапно офлајн.
По неколку недели & markdown i18n.site
Оваа статија ќе ја сподели техничката имплементација на i18n.site
чисто пребарување со целосен текст за да го i18n.site ефектот на пребарување.
За мали и средни чисто статични веб-локации, како што се документи/лични блогови, изградбата на самоизграден заднина за пребарување со целосен текст е премногу тешка, а пребарувањето со целосен текст без услуги е почест избор.
Решенијата за пребарување на целосен текст без сервер спаѓаат во две широки категории:
Прво, algolia.com даватели на услуги за пребарување од трети лица обезбедуваат предни компоненти за пребарување во целосен текст.
Таквите услуги бараат плаќање врз основа на обемот на пребарување и често се недостапни за корисниците во Кина поради проблеми како што е усогласеноста на веб-страниците.
Не може да се користи офлајн, не може да се користи на интранет и има големи ограничувања. Оваа статија не дискутира многу.
Вториот е чисто пребарување на целосен текст од предниот дел.
Во моментов, ElasticLunr.js чисто предни пребарувања со целосен текст lunrjs
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прелистувач не го сегментира
. ` .
Креирани се 5 табели за складирање на објекти во IndexedDB
:
word
зборови : id -doc
: id - url - Број на верзија на документотdocWord
: од документ id - збор idprefix
: од префикс - збор idrindex
: id - Документ id : Низа од броеви на линииПоминете во низата од документот url
и верзијата број ver
и побарајте дали документот постои во табелата doc
Ако не постои, креирајте превртен индекс. Во исто време, отстранете го превртениот индекс за оние документи што не биле предадени.
На овој начин може да се постигне инкрементално индексирање и да се намали износот на пресметка.
Во интеракцијата од предниот дел, лентата css напредок на вчитувањето на индексот може / се прикаже за да се избегне задоцнување при progress + за прв пат.
Проектот е 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
Саморазвиено чисто пребарување со отворен код, мало по големина и брз одговор, ги решава недостатоците на тековното чисто пребарување на целосен текст од предниот дел и обезбедува подобро корисничко искуство.