首頁 web前端 js教程 純前端倒排全文搜索

純前端倒排全文搜索

Oct 14, 2024 pm 02:27 PM

原文連結:https://i18n.site/blog/tech/search

順序

經過幾週的開發,i18n.site(純靜態Markdown多語言翻譯網站架設工具)現已支援純前端全文搜尋。

純前端倒排全文搜索純前端倒排全文搜索

本文將分享i18n.site純前端全文搜尋的技術實作。存取 i18n.site 體驗搜尋功能。

程式碼開源:搜尋核心/互動介面

無伺服器全文搜尋解決方案概述

對於文件/個人部落格等中小型純靜態網站,建立自建全文搜尋後端過於繁重,無服務全文搜尋是更常見的選擇。

無伺服器全文搜尋解決方案分為兩大類:

第一個涉及第三方搜尋服務供應商,例如 algolia.com,它們提供用於全文搜尋的前端元件。

此類服務需要根據搜尋量付費,且由於合規問題通常無法向中國大陸用戶提供。

它們不能離線或在內部網路上使用,並且有很大的限制。本文不再詳述。

第二類是純前端全文檢索。

目前常見的純前端全文檢索工具有lunrjs和ElasticLunr.js(基於lunrjs的二次開發)。

lunrjs 有兩種建立索引的方法,但都有各自的問題。

  1. 預建索引檔

由於索引包含了文件中的所有單字,因此其尺寸較大。
每次新增或修改文件時,都必須載入新的索引檔。
這會增加用戶等待時間並消耗大量頻寬。

  1. 動態載入文件並建立索引

建立索引是一項計算密集型任務,每次訪問時重建索引可能會導致明顯的延遲,從而導致糟糕的用戶體驗。


除了lunrjs之外,還有其他全文搜尋解決方案,例如:

fusejs,透過計算字串之間的相似度進行搜尋。

此方案效能較差,不適合全文檢索(參考Fuse.js 查詢時間長超過10秒,如何最佳化?)。

TinySearch使用布隆過濾器進行搜索,無法進行前綴搜索(例如輸入goo搜索good或google),無法實現自動完成效果。

針對現有解決方案的缺陷,i18n.site開發了全新的純前端全文搜尋解決方案,具有以下特點:

  1. 支援多語言搜索,體積小巧;使用 gzip 打包後,搜索內核只有 6.9KB(相比之下,lunrjs 為 25KB)
  2. 基於IndexedDB建立倒排索引,記憶體佔用量低,效能快
  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()
登入後複製

地點:

  • /p{P}/ 是符合標點符號的正規表示式,包括: ! " # $ % & ' ( ) * , - . / : ; ? @ [ ] ^ _ { | } ~. . p>
    • split('.' )是因為Firefox瀏覽器分詞不分詞。
    指數建構

    IndexedDB 中建立了 5 個物件儲存表:

      單字:id - 單字
    • doc: id - 文件 URL - 文件版本號
    • docWord:文件 id - 單字 id 陣列
    • prefix:前綴 - 單字 id 陣列
    • rindex:單字 id - 文件 id - 行號陣列
    透過傳入文件 url 和版本號 ver 的數組,檢查 doc 表中文件是否存在。如果不存在,則建立倒排索引。同時,未傳入文件的倒排索引將被刪除。

    此方法允許增量索引,減少計算負載。

    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.

    IndexedDB High Concurrent Writing

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

    Prefix Real-Time 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);
    };
    }

    Precision and Recall

    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.

    純前端倒排全文搜索

    On-Demand Loading

    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.

    Prefix Real-Time 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);
    };
    }

    Offline Availability

    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.

    Optimization for Displaying MarkDown Documents

    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.

    純前端倒排全文搜索

    Summary

    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.

以上是純前端倒排全文搜索的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1670
14
CakePHP 教程
1428
52
Laravel 教程
1329
25
PHP教程
1276
29
C# 教程
1256
24
Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

從C/C到JavaScript:所有工作方式 從C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript和Web:核心功能和用例 JavaScript和Web:核心功能和用例 Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

JavaScript在行動中:現實世界中的示例和項目 JavaScript在行動中:現實世界中的示例和項目 Apr 19, 2025 am 12:13 AM

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

了解JavaScript引擎:實施詳細信息 了解JavaScript引擎:實施詳細信息 Apr 17, 2025 am 12:05 AM

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python vs. JavaScript:社區,圖書館和資源 Python vs. JavaScript:社區,圖書館和資源 Apr 15, 2025 am 12:16 AM

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

Python vs. JavaScript:開發環境和工具 Python vs. JavaScript:開發環境和工具 Apr 26, 2025 am 12:09 AM

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

C/C在JavaScript口譯員和編譯器中的作用 C/C在JavaScript口譯員和編譯器中的作用 Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

See all articles