brief: | i18n.site цяпер падтрымлівае бессерверны паўнатэкставы пошук.
Гэты артыкул знаёміць з рэалізацыяй чыстай інтэрфейснай тэхналогіі паўнатэкставага пошуку, уключаючы інвертаваны індэкс, створаны IndexedDB, пошук па прэфіксах, аптымізацыю сегментацыі слоў і падтрымку некалькіх моў.
У параўнанні з існуючымі рашэннямі, чысты інтэрфейсны паўнатэкставы пошук i18n.site мае малы памер і хуткасць, падыходзіць для малых і сярэдніх вэб-сайтаў, такіх як дакументы і блогі, і даступны ў аўтаномным рэжыме.
Пасля некалькіх тыдняў распрацоўкі i18n.site (чыста статычны markdown multilingualtranslation & інструмент для стварэння вэб-сайтаў) цяпер падтрымлівае чысты інтэрфейсны паўнатэкставы пошук.
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
: Word 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
для апошняга слова пасля сегментацыі слова, каб знайсці ўсе словы з прэфіксам і шукаць паслядоўна.
Функцыя Anti-shake 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
Аўтаматычны пошук з адкрытым зыходным кодам, невялікі па памеры і хуткі адказ, ліквідуе недахопы цяперашняга поўнатэкставага пошуку і забяспечвае лепшы карыстацкі досвед.