brief: | и18н.сите сада подржава претрагу пуног текста без сервера.
Овај чланак уводи имплементацију чисте фронт-енд технологије претраживања пуног текста, укључујући обрнути индекс који је направио ИндекедДБ, претрагу префикса, оптимизацију сегментације речи и подршку за више језика.
У поређењу са постојећим решењима, чиста фронт-енд претрага целог текста и18н.сите је мале величине и брза, погодна за мале и средње веб локације као што су документи и блогови, и доступна је ван мреже.
Након неколико седмица развоја, 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сегментирање речи претраживача не сегментира
. ` .
5 табела за складиштење објеката креирано је у IndexedDB
:
word
: id -doc
: id - url - Број верзије документаdocWord
Низ : id - реч idprefix
: префикса - реч idrindex
: id - Документ id : Низ бројева линијаПроследите низ документа url
и верзије број ver
и потражите да ли документ постоји у табели doc
Ако не постоји, креирајте обрнути индекс. Истовремено, уклоните обрнути индекс за оне документе који нису прослеђени.
На овај начин се може постићи инкрементално индексирање и смањити количина обрачуна.
У фронт-енд интеракцији, трака тока учитавања индекса може да се прикаже да би се избегло кашњење при првом учитавању Погледајте „Трака напретка са анимацијом, заснована на једној progress + Чиста css имплементација“ енглески / кинески .
Пројекат је idb на основу асинхроне енкапсулације 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
Саморазвијена чиста фронт-енд претрага отвореног кода, мале величине и брзог одзива, решава недостатке тренутне чисте фронт-енд претраге целог текста и пружа боље корисничко искуство.