Pautan Asal: https://i18n.site/blog/tech/search
Selepas beberapa minggu pembangunan, i18n.site (terjemahan berbilang bahasa & alat pembinaan tapak web) kini menyokong carian teks penuh bahagian hadapan yang tulen.
Artikel ini akan berkongsi pelaksanaan teknikal carian teks penuh bahagian hadapan tulen i18n.site. Lawati i18n.site untuk merasai kefungsian carian.
Kod adalah sumber terbuka: Carian kernel / antara muka Interaktif
Untuk tapak web statik semata-mata dan bersaiz sederhana seperti dokumen/blog peribadi, membina bahagian belakang carian teks penuh binaan sendiri adalah terlalu berat dan carian teks penuh tanpa perkhidmatan ialah pilihan yang lebih biasa.
Penyelesaian carian teks penuh tanpa pelayan dibahagikan kepada dua kategori utama:
Yang pertama melibatkan penyedia perkhidmatan carian pihak ketiga seperti algolia.com yang menawarkan komponen bahagian hadapan untuk carian teks penuh.
Perkhidmatan sedemikian memerlukan pembayaran berdasarkan volum carian dan selalunya tidak tersedia kepada pengguna di tanah besar China kerana isu pematuhan.
Ia tidak boleh digunakan di luar talian atau pada intranet dan mempunyai had yang ketara. Artikel ini tidak akan menghuraikan lebih lanjut.
Kategori kedua ialah carian teks penuh bahagian hadapan tulen.
Pada masa ini, alatan carian teks penuh bahagian hadapan tulen biasa termasuk lunrjs dan ElasticLunr.js (pembangunan sekunder berdasarkan lunrjs).
lunrjs mempunyai dua kaedah untuk membina indeks, kedua-duanya dengan isu mereka sendiri.
Oleh kerana indeks termasuk semua perkataan daripada dokumen, ia bersaiz besar.
Setiap kali dokumen ditambah atau diubah suai, fail indeks baharu mesti dimuatkan.
Ini meningkatkan masa menunggu pengguna dan menggunakan sejumlah besar lebar jalur.
Membina indeks ialah tugas yang intensif dari segi pengiraan, dan membina semula indeks dengan setiap akses boleh menyebabkan kelewatan yang ketara, yang membawa kepada pengalaman pengguna yang buruk.
Selain lunrjs, terdapat penyelesaian carian teks penuh lain, seperti:
fusejs, yang mencari dengan mengira persamaan antara rentetan.
Penyelesaian ini mempunyai prestasi yang lemah dan tidak sesuai untuk carian teks penuh (rujuk Fuse.js Pertanyaan panjang mengambil masa lebih 10 saat, bagaimana untuk mengoptimumkan?).
TinySearch, yang menggunakan penapis Bloom untuk mencari, tidak boleh melakukan carian awalan (cth., memasukkan goo untuk mencari kebaikan atau google) dan tidak boleh mencapai kesan autolengkap.
Disebabkan oleh kelemahan penyelesaian sedia ada, i18n.site telah membangunkan penyelesaian carian teks penuh bahagian hadapan tulen baharu dengan ciri berikut:
Butiran pelaksanaan teknikal i18n.site akan diperkenalkan di bawah.
Pembahagian perkataan menggunakan Intl.Segmenter asli penyemak imbas, yang disokong oleh semua penyemak imbas arus perdana.
Kod skrip kopi untuk pembahagian perkataan adalah seperti berikut:
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()
Di mana:
Lima jadual storan objek dibuat dalam IndexedDB:
Dengan menghantar tatasusunan url dokumen dan nombor versi ver, jadual dokumen disemak untuk kewujudan dokumen. Jika ia tidak wujud, indeks terbalik dicipta. Pada masa yang sama, indeks terbalik untuk dokumen yang tidak dihantar masuk dikeluarkan.
Kaedah ini membenarkan pengindeksan tambahan, mengurangkan beban pengiraan.
In the front-end interface, a progress bar for index loading can be displayed to avoid lag during the initial load. See "Animated Progress Bar, Based on a Single progress + Pure CSS Implementation" English / Chinese.
The project is developed based on the asynchronous encapsulation of IndexedDB, idb.
IndexedDB reads and writes are asynchronous. When creating an index, documents are loaded concurrently to build the index.
To avoid data loss due to concurrent writes, you can refer to the following coffeescript code, which adds a ing cache between reading and writing to intercept competitive writes.
`coffee
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()
`
To display search results in real-time as the user types, for example, showing words like words and work that start with wor when wor is entered.
The search kernel uses the prefix table for the last word after segmentation to find all words with that prefix and search sequentially.
An anti-shake function, debounce (implemented as follows), is used in the front-end interaction to reduce the frequency of searches triggered by user input, thus minimizing computational load.
js
export default (wait, func) => {
var timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(func.bind(this, ...args), wait);
};
}
The search first segments the keywords entered by the user.
Assuming there are N words after segmentation, the results are first returned with all keywords, followed by results with N-1, N-2, ..., 1 keywords.
The search results displayed first ensure query precision, while subsequent loaded results (click the "Load More" button) ensure recall.
To improve response speed, the search uses the yield generator to implement on-demand loading, returning results after each limit query.
Note that after each yield, a new IndexedDB query transaction must be opened for the next search.
To display search results in real-time as the user types, for example, showing words like words and work that start with wor when wor is entered.
The search kernel uses the prefix table for the last word after segmentation to find all words with that prefix and search sequentially.
An anti-shake function, debounce (implemented as follows), is used in the front-end interaction to reduce the frequency of searches triggered by user input, thus minimizing computational load.
js
export default (wait, func) => {
var timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(func.bind(this, ...args), wait);
};
}
The index table does not store the original text, only words, reducing storage space.
Highlighting search results requires reloading the original text, and using service worker can avoid repeated network requests.
Also, because service worker caches all articles, once a search is performed, the entire website, including search functionality, becomes offline available.
The pure front-end search solution provided by i18n.site is optimized for MarkDown documents.
When displaying search results, the chapter name is shown, and clicking navigates to that chapter.
The pure front-end implementation of inverted full-text search, without the need for a server, is very suitable for small to medium-sized websites such as documents and personal blogs.
i18n.site's open-source self-developed pure front-end search is compact, responsive, and addresses the various shortcomings of current pure front-end full-text search solutions, providing a better user experience.
Atas ialah kandungan terperinci Carian Teks Penuh Terbalik Bahagian Hadapan Tulen. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!