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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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…