Elasticsearch - 倒排索引原理和簡易實現

倒排索引的功能設計

倒排索引(Inverted Index)是一種高效的數據結構,常用于全文搜索和信息檢索系統。它的核心思想是將文檔中每個關鍵字(term)與包含該關鍵字的文檔列表進行映射。

以下是實現倒排索引功能的設計步驟和代碼示例:

功能需求

  1. 文檔存儲

    • 存儲一組文檔,文檔可以是字符串(文本內容)。

  2. 索引構建

    • 從文檔中提取關鍵詞,構建倒排索引。

  3. 關鍵詞查詢

    • 根據用戶輸入的關鍵詞,快速返回包含該關鍵詞的文檔ID。

  4. 多關鍵詞查詢

    • 支持 AND、OR 等多關鍵詞查詢模式。


設計步驟

1. 數據結構
  • 使用以下數據結構:

    • Map<String, List<Integer>>(或 HashMap):每個關鍵詞映射到一個文檔ID列表。

    • List<String>:存儲原始文檔內容,用于返回查詢結果。

2. 倒排索引的構建
  • 遍歷所有文檔,分詞(Tokenization)提取關鍵詞。

  • 對于每個關鍵詞,將文檔ID添加到其倒排列表中。

3. 查詢功能
  • 單關鍵詞查詢:直接查找倒排索引。

  • 多關鍵詞查詢

    • AND 查詢:取關鍵詞對應的文檔列表的交集。

    • OR 查詢:取關鍵詞對應的文檔列表的并集。


Java實現代碼

import java.util.*;public class InvertedIndex {// 倒排索引結構:關鍵詞 -> 包含該關鍵詞的文檔ID列表private Map<String, List<Integer>> index;// 文檔存儲:文檔ID -> 文檔內容private List<String> documents;public InvertedIndex() {this.index = new HashMap<>();this.documents = new ArrayList<>();}// 添加文檔到系統并更新倒排索引public void addDocument(String document) {int docId = documents.size(); // 文檔ID為索引位置documents.add(document); // 添加文檔到文檔存儲// 分詞并更新倒排索引String[] tokens = tokenize(document);for (String token : tokens) {index.computeIfAbsent(token, k -> new ArrayList<>()).add(docId);}}// 分詞函數,簡單實現(按空格分詞并轉換為小寫)private String[] tokenize(String document) {return document.toLowerCase().split("\\W+"); // 使用正則分割}// 查詢單關鍵詞public List<String> search(String keyword) {keyword = keyword.toLowerCase();List<Integer> docIds = index.getOrDefault(keyword, new ArrayList<>());List<String> results = new ArrayList<>();for (int docId : docIds) {results.add(documents.get(docId));}return results;}// 查詢多個關鍵詞(AND 模式)public List<String> searchAnd(String... keywords) {List<Set<Integer>> resultSets = new ArrayList<>();for (String keyword : keywords) {keyword = keyword.toLowerCase();resultSets.add(new HashSet<>(index.getOrDefault(keyword, new ArrayList<>())));}// 求交集Set<Integer> intersection = resultSets.get(0);for (Set<Integer> resultSet : resultSets) {intersection.retainAll(resultSet);}// 返回結果List<String> results = new ArrayList<>();for (int docId : intersection) {results.add(documents.get(docId));}return results;}// 查詢多個關鍵詞(OR 模式)public List<String> searchOr(String... keywords) {Set<Integer> union = new HashSet<>();for (String keyword : keywords) {keyword = keyword.toLowerCase();union.addAll(index.getOrDefault(keyword, new ArrayList<>()));}// 返回結果List<String> results = new ArrayList<>();for (int docId : union) {results.add(documents.get(docId));}return results;}// 打印倒排索引(用于調試)public void printIndex() {for (Map.Entry<String, List<Integer>> entry : index.entrySet()) {System.out.println(entry.getKey() + " -> " + entry.getValue());}}// 測試方法public static void main(String[] args) {InvertedIndex invertedIndex = new InvertedIndex();// 添加文檔invertedIndex.addDocument("Hello world");invertedIndex.addDocument("Hello Java");invertedIndex.addDocument("Java is fun");invertedIndex.addDocument("Inverted index example");// 打印倒排索引invertedIndex.printIndex();// 查詢單關鍵詞System.out.println("Search 'Java': " + invertedIndex.search("Java"));// 查詢多個關鍵詞(AND)System.out.println("Search 'Hello' AND 'Java': " + invertedIndex.searchAnd("Hello", "Java"));// 查詢多個關鍵詞(OR)System.out.println("Search 'Java' OR 'example': " + invertedIndex.searchOr("Java", "example"));}
}

代碼說明

  1. 文檔存儲

    • documents 列表存儲所有文檔,文檔ID是其索引位置。

  2. 倒排索引

    • 使用 HashMap<String, List<Integer>> 存儲每個關鍵詞與對應文檔ID列表的映射。

    • computeIfAbsent 確保關鍵詞不存在時初始化列表。

  3. 查詢功能

    • 單關鍵詞:直接返回關鍵詞對應的文檔ID列表。

    • AND查詢:取所有關鍵詞的文檔ID列表交集。

    • OR查詢:取所有關鍵詞的文檔ID列表并集。

  4. 分詞與歸一化

    • 使用正則表達式按非字母數字字符分割,并將關鍵詞轉為小寫。


輸出示例

運行代碼后可能輸出如下:

hello -> [0, 1]
world -> [0]
java -> [1, 2]
is -> [2]
fun -> [2]
inverted -> [3]
index -> [3]
example -> [3]
Search 'Java': [Hello Java, Java is fun]
Search 'Hello' AND 'Java': [Hello Java]
Search 'Java' OR 'example': [Hello Java, Java is fun, Inverted index example]

總結

這個實現展示了一個簡單但功能齊全的倒排索引系統,適用于小型的全文檢索需求。如果需要處理大規模數據,可以進一步優化分詞、索引存儲(如基于磁盤存儲或分布式系統),并加入排名算法(如 TF-IDF)以提高查詢精度。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/916947.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/916947.shtml
英文地址,請注明出處:http://en.pswp.cn/news/916947.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C#開發的Panel里控件拖放例子 - 開源研究系列文章

上次寫了Panel的分頁滾動控件( C#開發的Panel滾動分頁控件&#xff08;滑動版&#xff09; - 開源研究系列文章 - Lzhdims Fashion - 博客園 )&#xff0c;但是主要是想寫一個Panel里控件拖放的效果&#xff0c;然后分頁控件用于Panel里控件的分頁。此文這次寫的是控件拖放效果…

Thinkph6中常用的驗證方式實例

我們在使用thinkphp6中的數據驗證時&#xff0c;如果使用不多的話&#xff0c;會經常遇到校驗不對&#xff0c;在這個小問題上折騰很多&#xff0c;索引就不用了。我還不如直接寫if條件來的迅捷&#xff01;&#xff01;下面把常見的校驗方法進行一下整理&#xff1a;protected…

分享一個FPGA寄存器接口自動化工具

FPGA模塊越寫越多&#xff0c;規范性和可移植性卻堪憂。要是有一個工具可以根據模塊接口描述文件生成verilog和c頭文件就好了。苦苦搜尋找到了幾款免費的工具&#xff0c;SystemRDL、cheby和rggen。筆者學習了下cheby和reksio&#xff0c;reksio是gui版的cheby&#xff0c;這是…

小程序中事件對象的屬性與方法

在小程序中&#xff0c;事件處理函數的參數為事件對象&#xff08;通常命名為 e&#xff09;&#xff0c;包含了事件相關的詳細信息&#xff08;如事件類型、觸發元素、傳遞的數據等&#xff09;。事件對象的屬性和方法因事件類型&#xff08;如點擊、輸入、觸摸等&#xff09;…

使用寶塔“PostgreSQL管理器”安裝的PostgreSQL,如何設置遠程連接?

安裝 PostgreSQL 使用寶塔“PostgreSQL管理器”安裝PostgreSQL&#xff0c;版本可以根據自己的需求來選擇&#xff0c;我這里使用的是16.1 創建數據庫 根據下圖所示步驟創建數據庫&#xff0c;其中 “訪問權限”一定要選擇“所有人”啟用遠程連接設置允許所有 IP 連接 listen_a…

論文:M矩陣

M矩陣是線性代數中的一個概念&#xff0c;它是一種特殊類型的矩陣&#xff0c;具有以下性質&#xff1a;非負的非對角線元素&#xff1a;矩陣的所有非對角線元素都是非負的&#xff0c;即對于矩陣MMM中的任意元素mijm_{ij}mij?&#xff0c;當i≠ji\neq jij時&#xff0c;有m…

跳躍表可視化深度解析:動態演示數據結構核心原理

跳躍表可視化深度解析&#xff1a;動態演示數據結構核心原理 一、跳躍表基礎概念與核心優勢 跳躍表&#xff08;SkipList&#xff09;是一種基于多層索引鏈表的數據結構&#xff0c;通過概率平衡實現高效的插入、刪除和查找操作。其核心優勢體現在&#xff1a; ?時間復雜度優…

《Sentinel服務保護實戰:控制臺部署與SpringCloud集成指南》

sentinel 介紹 Sentinel是阿里巴巴開源的一款服務保護框架&#xff0c;目前已經加入SpringCloudAlibaba中。官方網站&#xff1a; home | Sentinel Sentinel 的使用可以分為兩個部分: 核心庫&#xff08;Jar包&#xff09;&#xff1a;不依賴任何框架/庫&#xff0c;能夠運行…

IBM Watsonx BI:AI賦能的下一代商業智能平臺

產品概覽 IBM Watsonx BI 是基于 watsonx 企業級 AI 與數據平臺 構建的智能分析解決方案&#xff0c;專為現代化企業打造。它深度融合人工智能技術&#xff0c;突破傳統 BI 工具的限制&#xff0c;通過自動化數據洞察、自然語言交互和預測分析&#xff0c;幫助企業在復雜數據環…

Python實現GO鵝優化算法優化GBRT漸進梯度回歸樹回歸模型項目實戰

說明&#xff1a;這是一個機器學習實戰項目&#xff08;附帶數據代碼文檔&#xff09;&#xff0c;如需數據代碼文檔可以直接到文章最后關注獲取 或者私信獲取。 1.項目背景 隨著大數據和人工智能技術的快速發展&#xff0c;回歸預測在金融、氣象、能源等多個領域中扮演著至關…

深度學習計算(深度學習-李沐-學習筆記)

層和塊 單一輸出的線性模型&#xff1a;單個神經網絡 &#xff08;1&#xff09;接受一些輸入&#xff1b; &#xff08;2&#xff09;生成相應的標量輸出&#xff1b; &#xff08;3&#xff09;具有一組相關 參數&#xff08;parameters&#xff09;&#xff0c;更新這些參數…

leetcode熱題——搜索二維矩陣Ⅱ

目錄 搜索二維矩陣Ⅱ 題目描述 題解 解法一&#xff1a;暴力搜索 C 代碼實現 復雜度分析 解法二&#xff1a;二分查找 C 代碼實現 復雜度分析 解法三&#xff1a;Z字形查找 算法核心思想 算法步驟詳解 C 代碼實現 復雜度分析 搜索二維矩陣Ⅱ 題目描述 編寫一個…

牛客 - 數組中的逆序對

描述 在數組中的兩個數字&#xff0c;如果前面一個數字大于后面的數字&#xff0c;則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數P。并將P對1000000007取模的結果輸出。 即輸出P mod 1000000007 數據范圍&#xff1a; 對于 50% 的數據, size≤104 s…

Linux 日志管理與時鐘同步詳解

Linux 日志管理與時鐘同步詳解 一、日志管理 1. 日志服務概述 Linux 系統中主要有兩種日志服務&#xff0c;分別負責臨時和永久日志的管理&#xff1a; systemd-journald&#xff1a;存儲臨時日志&#xff0c;服務器重啟后日志會丟失&#xff0c;無需手動配置rsyslog&#xff1…

個人如何做股指期貨?

本文主要介紹個人如何做股指期貨&#xff1f;個人參與股指期貨交易需要遵循一定的流程和規則&#xff0c;同時需充分了解其高風險、高杠桿的特點&#xff0c;并做好風險管理。個人如何做股指期貨&#xff1f;一、了解股指期貨基礎股指期貨是以股票價格指數為標的物的金融期貨合…

設計模式-單例模式 Java

模式概述 單例模式&#xff08;Singleton Pattern&#xff09;是設計模式中最基礎但應用最廣泛的創建型模式之一&#xff0c;確保一個類僅有一個實例&#xff0c;并提供一個全局訪問點。這種模式在需要全局唯一對象的場景中至關重要&#xff0c;如配置管理、線程池、數據庫連接…

RFID 系統行業前沿洞察:技術躍遷與生態重構

在物聯網與人工智能深度融合的時代&#xff0c;RFID&#xff08;射頻識別&#xff09;系統正經歷從 “單品識別工具” 到 “智能決策中樞” 的范式轉變。這一技術憑借其非接觸式數據采集、環境適應性強、全生命周期追溯等特性&#xff0c;在醫療、制造、農業、環保等領域引發連…

實現implements InitializingBean, DisposableBean 有什么用

在 Spring 框架中&#xff0c;實現 InitializingBean 和 DisposableBean 接口用于管理 Bean 的生命周期回調&#xff0c;分別控制 Bean 的初始化后和銷毀前行為。具體作用如下&#xff1a;1. InitializingBean 接口public interface InitializingBean {void afterPropertiesSet…

GitLab 18.2 發布幾十項與 DevSecOps 有關的功能,可升級體驗【一】

沿襲我們的月度發布傳統&#xff0c;極狐GitLab 發布了 18.2 版本&#xff0c;該版本帶來了議題和任務的自定義工作流狀態、新的合并請求主頁、新的群組概覽合規儀表盤、下載安全報告的 PDF 導出文件、中心化的安全策略管理&#xff08;Beta&#xff09;等幾十個重點功能的改進…

如何快速把Clickhouse數據同步到Mysql

直接使用Clickhouse官方支持的Mysql引擎表的方式&#xff01; 一、首先創建Mysql引擎表&#xff1a; CREATE TABLE saas_analysis.t_page_view_new_for_write (id Int64,shop_id Nullable(Int64),session_id Nullable(String),client_id Nullable(String),one_id Nullable(Str…