brief: | i18n.site ondersteunt nu serverloos zoeken in volledige tekst.
Dit artikel introduceert de implementatie van puur front-end full-text zoektechnologie, inclusief de omgekeerde index gebouwd met IndexedDB, voorvoegselzoeken, optimalisatie van woordsegmentatie en meertalige ondersteuning.
Vergeleken met bestaande oplossingen is de puur front-end full-text search van i18n.site compact en snel, geschikt voor kleine en middelgrote websites zoals documenten en blogs, en is offline beschikbaar.
Na enkele weken van ontwikkeling ondersteunt i18n.site (een puur statische markdown-meertalige vertaal- en websitebouwtool) nu puur front-end volledig zoeken.
Dit artikel deelt de technische implementatie van i18n.site
's puur front-end volledig zoeken. Bezoek i18n.site om de zoekresultaten te ervaren.
Code open source: Zoekkernel / interactieve interface
Voor kleine en middelgrote, puur statische websites zoals documenten/persoonlijke blogs is het bouwen van een zelfgebouwde backend voor volledige tekstzoekfunctionaliteit te zwaar, en het gebruik van een servicevrije volledige tekstzoekoplossing is de meest gangbare keuze.
Serverloze full-text zoekoplossingen vallen in twee grote categorieën:
De eerste is het bieden van front-endcomponenten voor full-text zoeken door externe zoekserviceproviders zoals algolia.com.
Dergelijke diensten vereisen betaling op basis van zoekvolume en zijn vaak niet beschikbaar voor gebruikers in China vanwege compliance-problemen.
Zij kunnen niet offline worden gebruikt, kunnen niet op een intranet worden uitgevoerd en hebben grote beperkingen. Dit artikel bespreekt dit niet in detail.
De tweede is puur front-end full-text zoeken.
Momenteel zijn er enkele veelgebruikte pure frontend-oplossingen voor volledige tekstzoekfunctionaliteit, zoals lunrjs en ElasticLunr.js (een op lunrjs
gebaseerde secundaire ontwikkeling).
lunrjs
biedt twee manieren om indexen te bouwen, en beide hebben hun eigen problemen.
Vooraf gebouwde indexbestanden
Omdat de index woorden uit alle documenten bevat, is deze groot van formaat. Telkens wanneer een document wordt toegevoegd of gewijzigd, moet een nieuw indexbestand worden geladen. Dit verlengt de wachttijd van de gebruiker en verbruikt veel bandbreedte.
Laad documenten en bouw indexen in real-time
Het bouwen van een index is een rekenintensieve taak. Het opnieuw opbouwen van de index bij elke toegang veroorzaakt duidelijke vertragingen en een slechte gebruikerservaring.
Bijvoorbeeld, naast lunrjs
zijn er ook andere full-text zoekoplossingen zoals:
fusejs, dat de gelijkenis tussen te zoeken strings berekent.
Dit schema heeft een zeer slechte prestatie en kan niet worden gebruikt voor full-text zoeken (zie Fuse.js Lange zoekopdracht duurt meer dan 10 seconden, hoe optimaliseer je deze?).
TinySearch, dat gebruik maakt van een Bloom-filter voor het zoeken, kan geen voorvoegselzoeken uitvoeren (bijvoorbeeld, zoek op goo
voor good
, google
) en geen vergelijkbare automatisch aanvullende functie bieden.
Vanwege de gebreken van bestaande oplossingen heeft i18n.site
een nieuwe puur front-end full-text zoekoplossing ontwikkeld, met de volgende kenmerken:
gzip
is 6.9KB
(ter vergelijking: de grootte van lunrjs
is 25KB
)IndexedDB
, wat weinig geheugen in beslag neemt en snel isBijvoorbeeld, hieronder worden de technische implementatiedetails van i18n.site
in detail besproken.
Woordsegmentatie maakt gebruik van de oorspronkelijke browserinterface Intl.Segmenter
, die door alle reguliere browsers wordt ondersteund.
De woordsegmentatie in coffeescript
is als volgt:
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()
In:
/\p{P}/
is ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _
{ expressie die overeenkomt met leestekens | } ~. .</p><ul><li>
split('.')is omdat
Firefoxbrowserwoordsegmentatie
.` niet segmenteert.
In IndexedDB
zijn vijf objectopslagtabellen gemaakt:
word
: id - woordendoc
: id - Document URL - DocumentversienummerdocWord
: Array van document id - woord idprefix
: Array van voorvoegsel - woord idrindex
: Word id - Document id : Array van regelnummersGeeft de array met url
en versienummer ver
van de documenten door, en controleert of deze documenten in de tabel doc
bestaan. Als dat niet het geval is, wordt een omgekeerde index gemaakt. Tegelijkertijd worden de omgekeerde indices voor de niet doorgegeven documenten verwijderd.
Op deze manier kan incrementele indexering worden bereikt en wordt de hoeveelheid berekeningen verminderd.
Bij front-end-interactie kan de voortgangsbalk voor het laden van de index worden weergegeven om vertraging te voorkomen bij het voor de eerste keer laden. Zie "Voortgangsbalk met animatie, gebaseerd op een enkele progress + Pure css Implementatie" Engels / Chinees.
Het project is ontwikkeld op basis van de asynchrone wrapper idb voor IndexedDB.
Lees- en schrijfbewerkingen met IndexedDB zijn asynchroon. Wanneer een index wordt gemaakt, worden documenten gelijktijdig geladen om de index te maken.
Om gedeeltelijk gegevensverlies door concurrerende schrijfoperaties te voorkomen, kunt u de volgende coffeescript
-code raadplegen en een ing
-cache toevoegen tussen het lezen en schrijven om concurrerende schrijfoperaties te blokkeren.
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()
De zoekopdracht segmenteert eerst de door de gebruiker ingevoerde trefwoorden.
Stel dat er N
woorden zijn na de woordsegmentatie. Bij het retourneren van resultaten worden eerst resultaten geretourneerd die alle trefwoorden bevatten, en vervolgens resultaten met N-1
, N-2
, ..., 1
trefwoorden.
De zoekresultaten die eerst worden weergegeven, garanderen de nauwkeurigheid van de zoekopdracht, en de resultaten die vervolgens worden geladen (bijvoorbeeld, door op de knop 'Meer laden' te klikken) zorgen voor het terugroeppercentage.
Om de reactiesnelheid te verbeteren, gebruikt de zoekopdracht de yield
generator om laden op aanvraag te implementeren en wordt limit
keer geretourneerd wanneer een resultaat wordt opgevraagd.
Houd er rekening mee dat elke keer dat u na yield
opnieuw zoekt, u een zoektransactie van IndexedDB
opnieuw moet openen.
Om zoekresultaten weer te geven terwijl de gebruiker aan het typen is, worden, wanneer bijvoorbeeld wor
wordt ingevoerd, woorden weergegeven die beginnen met wor
zoals words
en work
.
De zoekkernel gebruikt de prefix
-tabel voor het laatste woord na woordsegmentatie om alle woorden te vinden die ervoor staan en in volgorde te zoeken.
Bij front-end-interactie wordt ook de anti-shake-functie debounce
gebruikt (zoals hieronder geïmplementeerd) om de frequentie van gebruikersinvoer die zoekopdrachten activeert te verminderen en de hoeveelheid berekeningen te verminderen.
export default (wait, func) => {
var timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(func.bind(this, ...args), wait);
};
}
De indextabel slaat niet de oorspronkelijke tekst op, alleen de woorden, waardoor de opslagruimte wordt verminderd.
Voor het markeren van zoekresultaten moet de oorspronkelijke tekst opnieuw worden geladen, en het matchen van service worker
kan herhaalde netwerkverzoeken voorkomen.
Omdat service worker
alle artikelen in het cachegeheugen opslaat, is de hele website, inclusief de zoekopdracht, offline beschikbaar zodra de gebruiker een zoekopdracht uitvoert.
De pure frontend-zoekoplossing van i18n.site
is geoptimaliseerd voor Markdown
-documenten.
Wanneer zoekresultaten worden weergegeven, wordt de hoofdstuknaam weergegeven en wordt er door het hoofdstuk genavigeerd wanneer erop wordt geklikt.
Puur front-end geïmplementeerd omgekeerd volledig zoeken vereist geen server en is zeer geschikt voor kleine en middelgrote websites zoals documenten en persoonlijke blogs.
i18n.site
's open source zelfontwikkelde puur front-end zoeksolution biedt compacte formaat, snelle respons en lost de tekortkomingen van huidige puur front-end full-text zoekoplossingen op, wat een betere gebruikerservaring biedt.