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.


Rent Front-End Invertert Fulltekstsøk

Innledning

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. Besøk i18n.site for å oppleve søkeeffekten.

Kode åpen kildekode: Søk i kjernen / Interaktivt grensesnitt

En oversikt over serverløse fulltekstsøkeløsninger

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 har to måter å bygge indekser på, og begge har sine egne problemer.

  1. Forhåndsbygde indeksfiler

    Fordi indeksen inneholder alle ord fra dokumentene, 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.

  2. Last inn dokumenter og bygg indekser på farten

    Å bygge en indeks er en beregningsintensiv oppgave. Hver gang du får tilgang til den, vil det føre til åpenbare etterslep og dårlig brukeropplevelse.


I tillegg til lunrjs finnes det noen andre fulltekstsøkeløsninger, som:

fusejs, beregner likheten mellom strenger for å søke.

Denne løsningen har svært dårlig ytelse og kan ikke brukes til fulltekstsøk (se Fuse.js Langt søk tar mer enn 10 sekunder, hvordan optimaliseres det?).

TinySearch, bruker Bloom-filteret for å søke, kan ikke brukes til prefikssøk (for eksempel å skrive goo og søke etter good og 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:

  1. Støtter flerspråklig søk, er liten i størrelse. Søkekjernen pakket med gzip er 6.9KB (som en sammenligning er lunrjs 25KB)
  2. Bygger en invertert indeks basert på IndexedDB, som tar opp mindre minne og er rask
  3. Når dokumenter legges til/endres, blir bare de endrede dokumentene re-indeksert, noe som reduserer beregningsmengden
  4. Støtter prefikssøk, som kan vise søkeresultater i sanntid mens brukeren skriver
  5. Tilgjengelig Offline

Nedenfor vil i18n.site tekniske implementeringsdetaljer bli introdusert i detalj.

Flerspråklig ordsegmentering

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()

Der:

Indeksbygg

5 objektlagringstabeller ble opprettet i IndexedDB :

Send 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 .

IndexedDB Høy Samtidig Skriving

Prosjektet er basert på asynkron innkapsling av IndexedDB ved hjelp av idb.

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()

Presisjon Og Tilbakekalling

Presisjon og tilbakekalling

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.

Last På Forespørsel

For å forbedre responshastigheten bruker søket yield generatoren for å implementere on-demand lasting, og returnerer limit gang et resultat spørres.

For å forbedre responshastigheten bruker søket yield generatoren for å implementere on-demand lasting, og returnerer limit gang et resultat spørres.

Prefiks Sanntidssøk

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);
  };
}

Tilgjengelig Offline

Tilgjengelig offline

Utheving av søkeresultater krever at den opprinnelige teksten lastes inn på nytt, og matchende service worker kan unngå gjentatte nettverksforespørsler.

Utheving av søkeresultater krever at den opprinnelige teksten lastes inn på nytt, og ved å bruke service worker kan man unngå gjentatte nettverksforespørsler.

Visningsoptimalisering Av MarkDown-Dokumenter

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.

Oppsummer

Summary

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.