brief: | Το i18n.site υποστηρίζει πλέον την αναζήτηση πλήρους κειμένου χωρίς διακομιστή.

Αυτό το άρθρο εισάγει την εφαρμογή της καθαρής τεχνολογίας αναζήτησης πλήρους κειμένου στο μπροστινό μέρος, συμπεριλαμβανομένου του ανεστραμμένου ευρετηρίου που δημιουργήθηκε από το IndexedDB, της αναζήτησης προθέματος, της βελτιστοποίησης τμηματοποίησης λέξεων και της υποστήριξης πολλών γλωσσών.

Σε σύγκριση με τις υπάρχουσες λύσεις, η αμιγώς μπροστινή αναζήτηση πλήρους κειμένου του i18n.site είναι μικρή σε μέγεθος και γρήγορη, κατάλληλη για μικρού και μεσαίου μεγέθους ιστότοπους, όπως έγγραφα και ιστολόγια, και είναι διαθέσιμη εκτός σύνδεσης.


Καθαρή Ανεστραμμένη Αναζήτηση Πλήρους Κειμένου Στο Front-End

Αλληλουχία

& από αρκετές εβδομάδες ανάπτυξης, markdown i18n.site

Αυτό το άρθρο θα μοιραστεί την τεχνική υλοποίηση της i18n.site καθαρής αναζήτησης πλήρους κειμένου για να i18n.site το αποτέλεσμα αναζήτησης.

Κώδικας / κώδικα :

Μια Επισκόπηση Λύσεων Αναζήτησης Πλήρους Κειμένου Χωρίς Διακομιστή

Για μικρού και μεσαίου μεγέθους αμιγώς στατικούς ιστότοπους, όπως έγγραφα/προσωπικά ιστολόγια, η δημιουργία ενός πλήρους κειμένου αναζήτησης που έχει κατασκευαστεί μόνος σας είναι πολύ βαριά και η αναζήτηση πλήρους κειμένου χωρίς υπηρεσίες είναι η πιο κοινή επιλογή.

Οι λύσεις αναζήτησης πλήρους κειμένου χωρίς διακομιστή χωρίζονται σε δύο μεγάλες κατηγορίες:

Πρώτον, algolia.com πάροχοι υπηρεσιών αναζήτησης τρίτων παρέχουν στοιχεία διεπαφής για αναζήτηση πλήρους κειμένου.

Τέτοιες υπηρεσίες απαιτούν πληρωμή με βάση τον όγκο αναζήτησης και συχνά δεν είναι διαθέσιμες στους χρήστες στην ηπειρωτική Κίνα λόγω ζητημάτων όπως η συμμόρφωση με τον ιστότοπο.

Δεν μπορεί να χρησιμοποιηθεί εκτός σύνδεσης, δεν μπορεί να χρησιμοποιηθεί στο intranet και έχει μεγάλους περιορισμούς. Αυτό το άρθρο δεν συζητά πολλά.

Το δεύτερο είναι η καθαρή αναζήτηση πλήρους κειμένου στο front-end.

Προς το παρόν, οι ElasticLunr.js αμιγώς μπροστινές αναζητήσεις πλήρους κειμένου lunrjs lunrjs

lunrjs Υπάρχουν δύο τρόποι δημιουργίας ευρετηρίων και και οι δύο έχουν τα δικά τους προβλήματα.

  1. Προκατασκευασμένα αρχεία ευρετηρίου

    Επειδή το ευρετήριο περιέχει λέξεις από όλα τα έγγραφα, είναι μεγάλο σε μέγεθος. Κάθε φορά που προστίθεται ή τροποποιείται ένα έγγραφο, πρέπει να φορτώνεται ένα νέο αρχείο ευρετηρίου. Θα αυξήσει τον χρόνο αναμονής του χρήστη και θα καταναλώσει πολύ εύρος ζώνης.

  2. Φορτώστε έγγραφα και δημιουργήστε ευρετήρια εν κινήσει

    Η δημιουργία ενός ευρετηρίου είναι μια εντατική υπολογιστική εργασία.


Εκτός από το lunrjs , υπάρχουν και κάποιες άλλες λύσεις αναζήτησης πλήρους κειμένου, όπως :

fusejs υπολογίστε την ομοιότητα μεταξύ των συμβολοσειρών για αναζήτηση.

Η απόδοση αυτής της λύσης είναι εξαιρετικά κακή και δεν μπορεί να χρησιμοποιηθεί για αναζήτηση πλήρους κειμένου (δείτε Fuse.js Το μεγάλο ερώτημα διαρκεί περισσότερα από 10 δευτερόλεπτα, πώς να το βελτιστοποιήσετε; ).

TinySearch χρησιμοποιήστε το φίλτρο Bloom για αναζήτηση, δεν μπορεί να χρησιμοποιηθεί για αναζήτηση προθέματος (για παράδειγμα, πληκτρολογήστε goo , αναζήτηση good , google ) και δεν μπορείτε να επιτύχετε παρόμοιο αποτέλεσμα αυτόματης ολοκλήρωσης.

Λόγω των ελλείψεων των υπαρχουσών λύσεων, i18n.site ανέπτυξε μια νέα λύση αναζήτησης πλήρους κειμένου καθαρού front-end, η οποία έχει τα ακόλουθα χαρακτηριστικά :

  1. Υποστηρίζει πολυγλωσσική αναζήτηση και είναι μικρό σε μέγεθος Το μέγεθος του πυρήνα αναζήτησης μετά τη συσκευασία gzip είναι 6.9KB (για σύγκριση, το μέγεθος του lunrjs είναι 25KB ).
  2. Δημιουργήστε έναν ανεστραμμένο δείκτη με βάση indexedb , ο οποίος καταλαμβάνει λιγότερη μνήμη και είναι γρήγορος.
  3. Όταν προστίθενται/τροποποιούνται έγγραφα, μόνο τα προστιθέμενα ή τροποποιημένα έγγραφα αναπροσαρμόζονται στο ευρετήριο, μειώνοντας τον όγκο των υπολογισμών.
  4. Υποστηρίζει αναζήτηση προθέματος, η οποία μπορεί να εμφανίζει αποτελέσματα αναζήτησης σε πραγματικό χρόνο ενώ ο χρήστης πληκτρολογεί.
  5. Διαθέσιμο Εκτός Σύνδεσης

Παρακάτω, θα παρουσιαστούν αναλυτικά 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()

σε:

Κτίριο Ευρετηρίου

Δημιουργήθηκαν 5 πίνακες αποθήκευσης αντικειμένων σε IndexedDB :

Περάστε στον πίνακα του εγγράφου url και του αριθμού έκδοσης ver και αναζητήστε εάν το έγγραφο υπάρχει στον πίνακα doc Εάν δεν υπάρχει, δημιουργήστε ένα ανεστραμμένο ευρετήριο. Ταυτόχρονα, αφαιρέστε το ανεστραμμένο ευρετήριο για εκείνα τα έγγραφα που δεν διαβιβάστηκαν.

Με αυτόν τον τρόπο, μπορεί να επιτευχθεί σταδιακή ευρετηρίαση και να μειωθεί το ποσό του υπολογισμού.

Στην css στο μπροστινό μέρος, η γραμμή προόδου φόρτωσης του ευρετηρίου μπορεί να εμφανιστεί για να / η καθυστέρηση κατά τη φόρτωση για πρώτη φορά , progress + .

IndexedDB Υψηλής Ταυτόχρονης Γραφής

Το έργο 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 για την τελευταία λέξη μετά την τμηματοποίηση λέξης για να βρει όλες τις λέξεις που έχουν το πρόθεμα του και να αναζητήσει με τη σειρά.

Η αντικραδασμική λειτουργία debounce χρησιμοποιείται επίσης στην αλληλεπίδραση με το μπροστινό μέρος (εφαρμόζεται ως εξής) για τη μείωση της συχνότητας των αναζητήσεων που ενεργοποιούν τα στοιχεία εισόδου του χρήστη και τη μείωση του όγκου υπολογισμού.

export default (wait, func) => {
  var timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(func.bind(this, ...args), wait);
  };
}

Διαθέσιμο Εκτός Σύνδεσης

Ο πίνακας ευρετηρίου δεν αποθηκεύει το αρχικό κείμενο, μόνο τις λέξεις, γεγονός που μειώνει τον όγκο αποθήκευσης.

Η επισήμανση των αποτελεσμάτων αναζήτησης απαιτεί επαναφόρτωση του αρχικού κειμένου και η αντιστοίχιση service worker μπορεί να αποφύγει τα επαναλαμβανόμενα αιτήματα δικτύου.

Ταυτόχρονα, επειδή service worker αποθηκεύει προσωρινά όλα τα άρθρα, μόλις ο χρήστης πραγματοποιήσει μια αναζήτηση, ολόκληρος ο ιστότοπος, συμπεριλαμβανομένης της αναζήτησης, είναι διαθέσιμος εκτός σύνδεσης.

Βελτιστοποίηση Εμφάνισης Εγγράφων MarkDown

Η καθαρή λύση αναζήτησης διεπαφής του i18n.site έχει βελτιστοποιηθεί για MarkDown έγγραφο.

Κατά την εμφάνιση των αποτελεσμάτων αναζήτησης, θα εμφανιστεί το όνομα του κεφαλαίου και το κεφάλαιο θα πλοηγηθεί όταν κάνετε κλικ.

Συνοψίζω

Αντεστραμμένη αναζήτηση πλήρους κειμένου που εφαρμόζεται αποκλειστικά στο μπροστινό μέρος, δεν απαιτείται διακομιστής. Είναι πολύ κατάλληλο για ιστοσελίδες μικρού και μεσαίου μεγέθους όπως έγγραφα και προσωπικά ιστολόγια.

i18n.site Ανοιχτού κώδικα αμιγώς διεπαφής αναζήτησης που έχει αναπτυχθεί μόνος του, μικρού μεγέθους και γρήγορης απόκρισης, επιλύει τα μειονεκτήματα της τρέχουσας αμιγούς διεπαφής αναζήτησης πλήρους κειμένου και παρέχει καλύτερη εμπειρία χρήστη.