brief: | i18n.site unterstützt jetzt die serverlose Volltextsuche.
In diesem Artikel wird die Implementierung der reinen Front-End-Volltextsuchtechnologie vorgestellt, einschließlich des von IndexedDB erstellten invertierten Indexes, der Präfixsuche, der Optimierung der Wortsegmentierung und der Unterstützung mehrerer Sprachen.
Im Vergleich zu bestehenden Lösungen ist die reine Front-End-Volltextsuche von i18n.site klein und schnell, eignet sich für kleine und mittlere Websites wie Dokumente und Blogs und ist offline verfügbar.
Nach mehreren Wochen der Entwicklung unterstützt i18n.site (ein rein statisches markdown multilingualtranslation & -Tool zum Erstellen von Websites) jetzt die reine Front-End-Volltextsuche.
In diesem Artikel wird die technische Implementierung der i18n.site
reinen Front-End-Volltextsuche vorgestellt, um den Sucheffekt zu i18n.site .
Code Open Source : Suchen Sie nach der / Kernel -Schnittstelle
Für kleine und mittlere rein statische Websites wie Dokumente/persönliche Blogs ist der Aufbau eines selbst erstellten Backends für die Volltextsuche zu aufwändig und die dienstfreie Volltextsuche ist die häufigere Wahl.
Lösungen für die serverlose Volltextsuche lassen sich in zwei große Kategorien einteilen:
Erstens, ähnlich algolia.com Drittanbieter von Suchdiensten stellen Frontend-Komponenten für die Volltextsuche bereit.
Solche Dienste erfordern eine Bezahlung basierend auf dem Suchvolumen und sind für Benutzer auf dem chinesischen Festland häufig aufgrund von Problemen wie der Einhaltung der Website-Compliance nicht verfügbar.
Es kann nicht offline verwendet werden, kann nicht im Intranet verwendet werden und unterliegt großen Einschränkungen. In diesem Artikel wird nicht viel besprochen.
Die zweite ist die reine Front-End-Volltextsuche.
Derzeit gehören zu den gängigen reinen Front-End-Volltextsuchen lunrjs und ElasticLunr.js (basierend auf lunrjs
Sekundärentwicklung).
lunrjs
Es gibt zwei Möglichkeiten, Indizes zu erstellen, und beide haben ihre eigenen Probleme.
Vorgefertigte Indexdateien
Da der Index Wörter aus allen Dokumenten enthält, ist er groß. Immer wenn ein Dokument hinzugefügt oder geändert wird, muss eine neue Indexdatei geladen werden. Dies erhöht die Wartezeit des Benutzers und verbraucht viel Bandbreite.
Laden Sie Dokumente und erstellen Sie Indizes im Handumdrehen
Das Erstellen eines Index ist eine rechenintensive Aufgabe. Die Neuerstellung des Index bei jedem Zugriff führt zu offensichtlichen Verzögerungen und einer schlechten Benutzererfahrung.
Neben lunrjs
gibt es noch einige andere Volltextsuchlösungen, wie zum Beispiel :
fusejs , Berechnen Sie die Ähnlichkeit zwischen den zu suchenden Zeichenfolgen.
Die Leistung dieser Lösung ist äußerst schlecht und kann nicht für die Volltextsuche verwendet werden (siehe Fuse.js Lange Abfrage dauert mehr als 10 Sekunden, wie optimiert man sie? ).
TinySearch , verwenden Sie den Bloom-Filter zum Suchen, können nicht für die Präfixsuche verwendet werden (geben Sie beispielsweise goo
ein, suchen Sie good
, google
) und können keinen ähnlichen automatischen Vervollständigungseffekt erzielen.
Aufgrund der Mängel bestehender Lösungen hat i18n.site
eine neue reine Front-End-Volltextsuchlösung entwickelt, die die folgenden Merkmale aufweist :
gzip
beträgt 6.9KB
(zum Vergleich: Die Größe von lunrjs
beträgt 25KB
).indexedb
, der weniger Speicher benötigt und schnell ist.Im Folgenden werden i18n.site
technische Implementierungsdetails im Detail vorgestellt.
Die Wortsegmentierung verwendet die native Wortsegmentierung Intl.Segmenter
des Browsers, und alle gängigen Browser unterstützen diese Schnittstelle.
Der Wortsegmentierungs coffeescript
Code lautet wie folgt
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}/
ist ein regulärer Ausdruck, der mit Satzzeichen übereinstimmt: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _
{ | } ~. .</p><ul><li>
split('.')liegt daran, dass
FirefoxBrowserwortsegmentierung
. ` nicht segmentiert.
5 Objektspeichertabellen wurden im Jahr IndexedDB
erstellt :
word
: id - Wörterdoc
: id - Dokument url - DokumentversionsnummerdocWord
: Array von Dokument id - Wort idprefix
: Array von Präfix - Wort idrindex
: Wort id - Dokument id : Array von ZeilennummernÜbergeben Sie das Array von Dokument url
und Versionsnummer ver
und suchen Sie in Tabelle doc
, ob das Dokument vorhanden ist. Wenn es nicht vorhanden ist, erstellen Sie einen invertierten Index. Entfernen Sie gleichzeitig den invertierten Index für die Dokumente, die nicht übergeben wurden.
Auf diese Weise kann eine inkrementelle Indizierung erreicht und der Rechenaufwand reduziert werden.
In der Front-End-Interaktion kann der Ladefortschrittsbalken des Index angezeigt werden, um Verzögerungen beim ersten Laden zu vermeiden. Siehe „Fortschrittsbalken mit Animation, basierend auf einer einzelnen progress + Pure css -Implementierung“ Englisch / Chinesisch .
Das Projekt idb auf der asynchronen Kapselung von IndexedDB
IndexedDB-Lese- und Schreibvorgänge erfolgen asynchron. Beim Erstellen eines Index werden Dokumente gleichzeitig geladen, um den Index zu erstellen.
Um einen teilweisen Datenverlust durch konkurrierendes Schreiben zu vermeiden, können Sie sich auf den coffeescript
Code unten beziehen und zwischen Lesen und Schreiben einen ing
Cache hinzufügen, um konkurrierende Schreibvorgänge abzufangen.
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()
Bei der Suche werden zunächst die vom Benutzer eingegebenen Schlüsselwörter segmentiert.
Gehen Sie davon aus, dass nach der Wortsegmentierung N
Wörter vorhanden sind. Bei der Rückgabe von Ergebnissen werden zuerst Ergebnisse zurückgegeben, die alle Schlüsselwörter enthalten, und dann werden Ergebnisse zurückgegeben, N-1
, N-2
, ..., 1
Schlüsselwörter enthalten.
Die zuerst angezeigten Suchergebnisse stellen die Genauigkeit der Abfrage sicher, und die anschließend geladenen Ergebnisse (klicken Sie auf die Schaltfläche „Mehr laden“) stellen die Rückrufrate sicher.
Um die Antwortgeschwindigkeit zu verbessern, verwendet die Suche den yield
Generator, um das Laden bei Bedarf zu implementieren, und gibt limit
Mal zurück, wenn ein Ergebnis abgefragt wird.
Beachten Sie, dass Sie jedes Mal, wenn Sie erneut nach yield
suchen, eine Abfragetransaktion von IndexedDB
erneut öffnen müssen.
Um Suchergebnisse anzuzeigen, während der Benutzer beispielsweise wor
eingibt, werden Wörter mit dem Präfix wor
wie words
und work
angezeigt.
Der Suchkernel verwendet die prefix
Tabelle für das letzte Wort nach der Wortsegmentierung, um alle Wörter mit diesem Präfix zu finden und der Reihe nach zu suchen.
Die Anti-Shake-Funktion debounce
wird auch in der Front-End-Interaktion verwendet (implementiert wie folgt), um die Häufigkeit von Benutzereingaben zu reduzieren, die Suchen auslösen, und den Rechenaufwand zu reduzieren.
export default (wait, func) => {
var timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(func.bind(this, ...args), wait);
};
}
In der Indextabelle wird nicht der Originaltext, sondern nur die Wörter gespeichert, wodurch sich der Speicherplatz verringert.
Das Hervorheben von Suchergebnissen erfordert das erneute Laden des Originaltexts. Durch die Übereinstimmung mit service worker
können wiederholte Netzwerkanfragen vermieden werden.
Da service worker
alle Artikel zwischenspeichert, ist gleichzeitig die gesamte Website, einschließlich der Suche, offline verfügbar, sobald der Benutzer eine Suche durchführt.
Die reine Front-End-Suchlösung von i18n.site
ist für MarkDown
Dokumente optimiert.
Bei der Anzeige von Suchergebnissen wird der Kapitelname angezeigt und beim Anklicken wird durch das Kapitel navigiert.
Invertierte Volltextsuche, rein im Frontend implementiert, kein Server erforderlich. Es eignet sich sehr gut für kleine und mittelgroße Websites wie Dokumente und persönliche Blogs.
i18n.site
Die von Open Source selbst entwickelte reine Front-End-Suche mit geringer Größe und schneller Reaktion behebt die Mängel der aktuellen reinen Front-End-Volltextsuche und bietet eine bessere Benutzererfahrung.