brief: | i18n.site støtter nå serverløst fulltekstsøk.
Denne artikkelen introduserer implementeringen av ren front-end fulltekstsøketeknologi, inkludert invertert indeks bygget av IndexedDB, prefikssøk, ordsegmenteringsoptimalisering og flerspråksstøtte.
Sammenlignet med eksisterende løsninger, er i18n.sites rene front-end fulltekstsøk lite i størrelse og raskt, egnet for små og mellomstore nettsteder som dokumenter og blogger, og er tilgjengelig offline.
Etter flere uker med utvikling, støtter i18n.site (et rent statisk markdown flerspråklig oversettelse & nettstedbyggingsverktøy) nå rent front-end fulltekstsøk.
Denne artikkelen vil dele den tekniske implementeringen av i18n.site
rent front-end fulltekstsøk. i18n.site for å oppleve søkeeffekten.
Kode åpen kildekode : Søk i kjernen / interaktivt grensesnitt
For små og mellomstore rent statiske nettsteder som dokumenter/personlige blogger er det for tungt å bygge en selvbygd fulltekstsøkeside, og tjenestefritt fulltekstsøk er det vanligste valget.
Serverløse fulltekstsøkeløsninger faller inn i to brede kategorier:
For det første tilbyr lignende algolia.com Tredjeparts søketjenesteleverandører front-end-komponenter for fulltekstsøk.
Slike tjenester krever betaling basert på søkevolum, og er ofte utilgjengelige for brukere i fastlands-Kina på grunn av problemer som nettstedsoverholdelse.
Den kan ikke brukes offline, kan ikke brukes på intranettet, og har store begrensninger. Denne artikkelen diskuterer ikke mye.
Det andre er rent front-end fulltekstsøk.
For tiden inkluderer vanlige rene front-end fulltekstsøk lunrjs og ElasticLunr.js (basert på lunrjs
sekundær utvikling).
lunrjs
Det er to måter å bygge indekser på, og begge har sine egne problemer.
Forhåndsbygde indeksfiler
Fordi indeksen inneholder ord fra alle dokumenter, er den stor i størrelse. Hver gang et dokument legges til eller endres, må en ny indeksfil lastes inn. Det vil øke brukerens ventetid og forbruke mye båndbredde.
Last inn dokumenter og bygg indekser på farten
Å bygge en indeks er en beregningsintensiv oppgave Å gjenoppbygge indeksen hver gang du får tilgang til den vil føre til åpenbare etterslep og dårlig brukeropplevelse.
I tillegg til lunrjs
finnes det noen andre fulltekstsøkeløsninger, som :
fusejs , beregne likheten mellom strenger for å søke.
Ytelsen til denne løsningen er ekstremt dårlig og kan ikke brukes til fulltekstsøk (se Fuse.js Langt søk tar mer enn 10 sekunder, hvordan optimaliseres det? ).
TinySearch , bruk Bloom-filteret for å søke, kan ikke brukes til prefikssøk (skriv for eksempel goo
, søk good
, google
), og kan ikke oppnå lignende automatisk fullføringseffekt.
På grunn av manglene ved de eksisterende løsningene utviklet i18n.site
en ny ren front-end fulltekstsøkeløsning, som har følgende egenskaper :
gzip
er 6.9KB
(til sammenligning er størrelsen på lunrjs
25KB
).indexedb
, som tar opp mindre minne og er rask.Nedenfor vil i18n.site
tekniske implementeringsdetaljer bli introdusert i detalj.
Ordsegmentering bruker nettleserens opprinnelige ordsegmentering Intl.Segmenter
, og alle vanlige nettlesere støtter dette grensesnittet.
Ordsegmentering coffeescript
koden er som følger
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()
i:
/\p{P}/
er et regulært uttrykk som samsvarer med tegnsettingstegn. Spesifikke samsvarende symboler inkluderer: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _
{ | } ~. .</p><ul><li>
split('.')er fordi
Firefoxnettleserordsegmentering ikke segmenterer
. ` .
5 objektlagringstabeller ble opprettet i IndexedDB
:
word
: id -doc
: id - Dokument url - DokumentversjonsnummerdocWord
: Matrise av dokument id - ord idprefix
: Matrise med prefiks - ord idrindex
: Word id - Dokument id : Matrise med linjenummerSend inn matrisen til dokument url
og versjonsnummer ver
, og søk om dokumentet finnes i tabell doc
Hvis det ikke finnes, oppretter du en invertert indeks. Fjern samtidig den inverterte indeksen for de dokumentene som ikke ble sendt inn.
På denne måten kan inkrementell indeksering oppnås og beregningsmengden reduseres.
I front-end-interaksjon kan lastefremdriftslinjen til indeksen vises for å unngå etterslep ved innlasting for første gang Se "Fremdriftslinje med animasjon, basert på en enkelt progress + Ren css Implementering" Engelsk / Kinesisk .
Prosjektet er idb basert på asynkron innkapsling av IndexedDB
IndexedDB lesing og skriving er asynkrone. Når du oppretter en indeks, vil dokumenter lastes samtidig for å lage indeksen.
For å unngå delvis datatap forårsaket av konkurrerende skriving, kan du referere til coffeescript
koden nedenfor og legge til en ing
cache mellom lesing og skriving for å avskjære konkurrerende skrivinger.
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()
Søket vil først segmentere søkeordene som er angitt av brukeren.
Anta at det er N
ord etter ordsegmenteringen. Når du returnerer resultater, vil resultater som inneholder alle søkeord bli returnert først, og deretter vil resultater som inneholder N-1
, N-2
,..., 1
nøkkelord bli returnert.
Søkeresultatene som vises først, sikrer nøyaktigheten av søket, og resultatene som lastes inn etterpå (klikk på last mer-knappen) sikrer tilbakekallingsfrekvensen.
For å forbedre responshastigheten bruker søket yield
generatoren for å implementere on-demand lasting, og returnerer limit
gang et resultat spørres.
Merk at hver gang du søker på nytt etter yield
, må du gjenåpne en spørringstransaksjon på IndexedDB
.
For å vise søkeresultater mens brukeren skriver, for eksempel når wor
skrives inn, vises ord med prefiks med wor
som words
og work
.
Søkekjernen vil bruke prefix
tabellen for det siste ordet etter ordsegmentering for å finne alle ord med prefiks, og søke i rekkefølge.
Anti-shake funksjon debounce
brukes også i front-end interaksjon (implementert som følger) for å redusere frekvensen av brukerinndata som utløser søk og redusere mengden av beregninger.
export default (wait, func) => {
var timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(func.bind(this, ...args), wait);
};
}
Indekstabellen lagrer ikke originalteksten, bare ordene, noe som reduserer lagringsmengden.
Utheving av søkeresultater krever at den opprinnelige teksten lastes inn på nytt, og matchende service worker
kan unngå gjentatte nettverksforespørsler.
Samtidig, fordi service worker
cacher alle artikler, er hele nettstedet, inkludert søket, tilgjengelig frakoblet når brukeren utfører et søk.
i18n.site
rene front-end søkeløsning er optimalisert for MarkDown
dokumenter.
Når du viser søkeresultater, vil kapittelnavnet vises, og kapittelet vil bli navigert når du klikker på det.
Invertert fulltekstsøk implementert utelukkende på grensesnittet, ingen server nødvendig. Den egner seg veldig godt for små og mellomstore nettsider som dokumenter og personlige blogger.
i18n.site
Åpen kildekode egenutviklet rene front-end-søk, liten i størrelse og rask respons, løser manglene ved dagens rene front-end fulltekstsøk og gir en bedre brukeropplevelse.