ElasticSearch核心技术解析:倒排索引与IK分词器如何解决中文搜索痛点

news/2025/2/26 11:15:39

在传统数据库中,模糊查询往往难以应对现实中的复杂情况。随着数据量的增加,查询时间显著变慢,功能也相对单一。当搜索时出现错别字或拼音输入时,搜索结果往往不尽如人意。因此,我们需要学习一种强大的搜索框架技术——ElasticSearch。

倒排索引

在传统的模糊搜索中,系统会从表中逐条读取数据,筛选出与模糊搜索条件相关的记录。这种方式通常使用B+树来建立索引,但由于索引与每条数据的内容没有直接关联,导致搜索时需要逐条检索,效率较低。

倒排索引

倒排索引是ElasticSearch等现代搜索引擎的核心技术之一。它引入了文档词条两个概念:

  • 文档:相当于数据库中的一条记录。

  • 词条:对文档内容进行分词处理。例如,句子“我是倒排索引”可以通过特定算法拆分为“我”、“是”、“倒排”、“索引”等词条。这些词条可能还包含其他语义相关的词语。

倒排索引的工作原理

假设我们有以下商品数据:

  1. "黑玩具"

  2. "红玩具"

  3. "红书包"

倒排索引会对这些文档进行词条划分,并建立词条与文档编号的映射关系:

  • 黑:1

  • 玩具:1, 2

  • 红:2, 3

  • 书包:3

当用户搜索“粉玩具”时,系统会首先对搜索词进行分词处理,得到“粉”和“玩具”两个词条。然后,系统会在倒排索引中查找这些词条对应的文档编号:

  • “粉”没有对应的文档编号。

  • “玩具”对应的文档编号是1和2。

最终,系统会返回文档编号为1和2的结果。由于词条和文档编号都建立了索引,搜索效率非常高。

倒排索引的优势

  1. 高效检索:通过词条与文档编号的映射,系统可以快速定位相关文档,避免了全表扫描。

  2. 容错性强:即使搜索词中存在错别字或拼音输入,系统仍然可以通过分词和索引匹配找到相关结果。

  3. 支持复杂查询:倒排索引支持多种查询方式,如布尔查询、短语查询、范围查询等,能够满足多样化的搜索需求。

IK分词器

ElasticSearch 依靠倒排索引来实现高效的全文搜索,而倒排索引的核心在于分词。对于中文文本,分词尤为重要,因为中文不像英文那样有天然的空格分隔。IK分词器是一个专门为中文设计的分词器,它能够将连续的汉字序列切分成有意义的词语,而不是简单地将每个字分开。这种分词方式不仅保留了语句的完整性,还方便了词条的创建和索引。

在 IK 分词器的配置中,IKAnalyzer.cfg.xml 文件用于对分词行为进行定制化配置。例如,当网络新梗或流行语出现时,传统的分词规则可能无法正确识别这些新词,导致分词结果不准确。通过修改配置文件,我们可以动态地扩展词典或调整分词规则,以适应实际需求。

以下是一个典型的 IKAnalyzer.cfg.xml 配置文件示例:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
	<comment>IK Analyzer 扩展配置</comment>
	<entry key="ext_dict">ext.dic</entry>
	<entry key="ext_stopwords"></entry>
</properties>
配置文件解析:
  1. ext_dict:用于指定扩展词典文件(如 ext.dic)。扩展词典允许用户添加新词或专有名词,确保这些词在分词时不会被错误地拆分。例如,网络流行语“内卷”、“躺平”等可以通过扩展词典加入分词器的词库。

  2. ext_stopwords:用于指定停用词文件。停用词是指在文本中出现频率较高但对搜索结果影响较小的词,例如“的”、“了”、“是”等。通过配置停用词,可以减少索引的大小,提高搜索效率。

IK分词器的两种模式:
  1. ik_smart:智能分词模式,采用粗粒度分词策略。这种模式会将文本切分成较少的词条,适合用于搜索引擎的初步筛选。例如,句子“人工智能技术”在 ik_smart 模式下可能只会分成“人工智能”和“技术”两个词条。

  2. ik_max_word:细粒度分词模式,采用最大分词策略。这种模式会尽可能多地将文本切分成不同的词条,适合用于需要高精度的场景。例如,句子“人工智能技术”在 ik_max_word 模式下可能会分成“人工”、“智能”、“人工智能”、“技术”等多个词条。

基本概念

ElasticSearch 的许多概念可以从 MySQL 中延伸理解:

  • 索引(Index):相当于 MySQL 中的表(Table),用于存储相关数据。

  • 字段(Field):相当于 MySQL 中的列(Column),用于定义数据的属性。

  • 文档(Document):相当于 MySQL 中的一行数据(Row),但在 ElasticSearch 中,文档是以 JSON 格式存储的。

  • 映射(Mapping):相当于 MySQL 的表结构(Schema),用于定义字段的数据类型和约束。

与 MySQL 不同,ElasticSearch 将每一行数据转换为 JSON 格式存储,这种设计使其在处理非结构化或半结构化数据时更加灵活。此外,ElasticSearch 在应对大规模数据搜索场景时表现出更高的效率,尤其是在全文搜索和复杂查询方面。

然而,MySQL 在数据安全性和事务支持方面更具优势,适合需要强一致性和复杂事务处理的场景。

索引库操作

索引相当于数据库中的表, 映射相当于数据库的表结构, 用来进行数据的约束, 要想进行倒排索引就要设置索引和映射

Mapping映射属性

在数据建模和搜索引擎配置中,映射属性(Mapping)用于定义字段的类型及其处理方式。以下是常见的字段类型及其相关属性:

字段类型
  1. 字符串类型:

    • Text: 适用于需要分词的文本字段

    • Keyword: 适用于不需要分词的精确文本,如品牌名称、国家代码等。

  2. 数字类型:

    • Integer: 32位整数。

    • Long: 64位整数。

    • Short: 16位整数。

    • Double: 双精度浮点数。

    • Float: 单精度浮点数。

    • Byte: 8位整数。

  3. 布尔类型:

    • Boolean: 表示真或假的值。

  4. 日期类型:

    • Date: 用于存储日期和时间。

  5. 对象类型:

    • Object: 用于嵌套的复杂数据结构。

其他属性
  • Index: 确定字段是否被索引。如果设置为false,该字段将不会被搜索,但仍可存储在文档中。

  • Properties: 用于定义嵌套字段或子字段的结构。

  • Analyzer: 指定用于分词的分词器类型,适用于Text类型的字段。

索引库

索引库的创建与映射设置

  1. 创建索引库并设置映射
    • 在Elasticsearch中,创建索引库的同时可以定义映射(mappings),映射用于描述索引库中文档的结构,包括字段的类型等信息。以下是创建索引库并设置映射的基本操作:
    • 使用PUT请求来创建索引库并设置映射。例如,创建一个名为my_index的索引库:
      • 在上述示例中:
        • 对于title字段,它被定义为text类型,并且还定义了一个子字段keyword,这个子字段也是keyword类型。这种结构很常见,text类型适合用于全文搜索,而keyword类型适合用于精确匹配,比如过滤或者排序。
        • 对于price字段,它是double类型,并且设置了"index": false。这意味着这个字段不会被索引,不能用于搜索,但可以在查询结果中返回该字段的值。
    PUT /my_index
    {
        "mappings": {
            "properties": {
                "title": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword"
                        }
                    }
                },
                "price": {
                    "type": "double",
                    "index": false
                }
            }
        }
    }

获取索引库​​​

  1. 查询索引库是否存在及基本信息
    • 使用GET请求可以获取索引库的信息。例如,要获取名为my_index的索引库的信息:
      • 如果索引库存在,Elasticsearch会返回该索引库的各种元数据信息,如索引的设置(包括分片数量、副本数量等)、映射等信息。如果索引库不存在,则会返回相应的错误提示。
    GET /my_index

添加新字段

  1. 注意事项
    • 在Elasticsearch中,如果直接在已经存在的索引库中进行字段修改,可能会导致倒排索引重新排列。当索引库中的数据量非常庞大时,这个操作可能会消耗大量的资源,甚至可能使服务器瘫痪。
  2. 正确的添加新字段方式
    • 要添加新字段,应该使用PUT请求针对索引库的_mapping端点进行操作。例如,要在my_index索引库中添加一个名为description的新字段,类型为text
      • 这种方式相对比较安全,并且Elasticsearch会根据新的映射调整索引结构,尽量减少对现有数据和搜索性能的影响。
    PUT /my_index/_mapping
    {
        "properties": {
            "description": {
                "type": "text"
            }
        }
    }

删除索引库

  1. 执行删除操作
    • 如果要删除一个名为my_index的索引库,可以使用DELETE请求:
      • 在执行删除操作之前,需要谨慎考虑,因为一旦索引库被删除,其中所有的数据都将永久丢失,并且无法恢复。
    DELETE /my_index

文档操作

新增文档

  1. 基本语法
    • 使用POST请求向指定索引库的_doc路径下添加文档,并可指定文档ID。
    • 格式:POST /索引库名/_doc/文档id
    • 示例:
    POST /my_index/_doc/1
    {
        "title": "示例文档",
        "content": "这是新增文档的内容"
    }
    • 若不指定文档ID,Elasticsearch会自动生成一个唯一ID。
    POST /my_index/_doc/
    {
        "title": "自动生成ID的文档",
        "content": "内容"
    }

获取文档

  1. 基本语法
    • 使用GET请求通过索引库名、_doc路径和文档ID来获取特定文档。
    • 格式:GET /索引库名/_doc/{id}
    • 示例:
      • 若文档存在,将返回该文档的详细信息;若不存在,会返回相应错误提示。
    GET /my_index/_doc/1

删除文档

  1. 基本语法
    • 使用DELETE请求通过索引库名、_doc路径和文档ID来删除特定文档。
    • 格式:DELETE /索引库名/_doc/{id}
    • 示例:
      • 成功删除会返回相应成功提示,若文档不存在则返回错误提示。
    DELETE /my_index/_doc/1

修改文档

一、全量修改

  1. 操作原理
    • 全量修改意味着对文档进行较为彻底的更新操作。如果目标文档在索引库中已经存在,那么会先删除原来的文档,然后再新增一个文档。如果该文档在索引库中原本就不存在,则会直接重新创建这个文档。
  2. 操作示例
    • 假设我们有一个名为“my_index”的索引库,并且要修改或者创建一个id为“1”的文档。其操作如下:
    • 使用的API为:PUT /my_index/_doc/1
    • 文档内容示例:
    {
        "title": "新的标题",
        "content": "这是全新的内容"
    }

二、局部修改

  1. 操作原理
    • 局部修改主要是针对文档的部分属性进行修改。这种修改方式不需要删除整个文档再重新创建,而是只更新指定的部分属性,从而节省资源和时间。
  2. 操作示例
    • 同样以“my_index”索引库中id为“1”的文档为例,如果只想修改其中“title”这个属性。
    • 使用的API为:POST /my_index/_update/1
    • 文档内容示例:
    {
        "doc": {
            "title": "修改后的标题"
        }
    }


http://www.niftyadmin.cn/n/5868611.html

相关文章

Linux权限 -- 开发工具

文章目录 包管理器yumyum具体操作 Linux编辑器 - vim的使用vimvim的多模式 包管理器yum Linux中安装软件&#xff1a; 1.源码安装 2. 软件包安装 – rpm 3. 包管理器yum(centos) apt/apt-get(ubuntu) 为什么有包管理器&#xff1f; 包管理器会自动帮我们解决包依赖的问题 2. 什…

蓝桥杯嵌入式客观题以及解释

第十一届省赛&#xff08;大学组&#xff09; 1.稳压二极管时利用PN节的反向击穿特性制作而成 2.STM32嵌套向量终端控制器NVIC具有可编程的优先等级 16 个 3.一个功能简单但是需要频繁调用的函数&#xff0c;比较适用内联函数 4.模拟/数字转换器的分辨率可以通过输出二进制…

博客系统完整开发流程

前言 通过前⾯课程的学习, 我们掌握了Spring框架和MyBatis的基本使用, 并完成了图书管理系统的常规功能开发, 接下来我们系统的从0到1完成⼀个项⽬的开发. 企业开发的流程 1. 需求评审(产品经理(PM)会和运营(想口号),UI,测试,开发等沟通) ,会涉及到背景/目标/怎么做,可能会有多…

娛閑放鬆篇2

最近看了好多動畫和以前的新聞&#xff0c;都挺有想法&#xff0c;可以了解一下 有些是N年前的&#xff0c;希望見怪莫怪 若說如何用最小作用量去理解世界觀的話&#xff0c;其實就是書&#xff0c;以動畫的角度來看&#xff0c;日本動畫足以 一.高達系列 一系列的利用巨大…

岳阳市美术馆预约平台(小程序论文源码调试讲解)

第4章 系统设计 一个成功设计的系统在内容上必定是丰富的&#xff0c;在系统外观或系统功能上必定是对用户友好的。所以为了提升系统的价值&#xff0c;吸引更多的访问者访问系统&#xff0c;以及让来访用户可以花费更多时间停留在系统上&#xff0c;则表明该系统设计得比较专…

Kotlin 知识点二 延迟初始化和密封类

对变量延迟初始化 Kotlin 语言的许多特性&#xff0c;包括变量不可变&#xff0c;变量不可为空&#xff0c;等等。这些特性 都是为了尽可能地保证程序安全而设计的&#xff0c;但是有些时候这些特性也会在编码时给我们带来不 少的麻烦。 比如&#xff0c;如果你的类中存在很多…

阳光高考瑞数6vmp算法还原

URL aHR0cHM6Ly9nYW9rYW8uY2hzaS5jb20uY24v这个站平时没有防护的&#xff0c;只有在平时填报高峰期&#xff0c;才会出来防护&#xff0c;也是为了防护自动脚本吧瑞数就是典型的cookie反爬 O开头cookie 6开头6代vmp&#xff0c;P值是加密的cookie&#xff0c;只有带上0开头的…

vue3.0将后端返回的word文件流转换为pdf并导出+html2pdf.js将页面导出为pdf

实现思路 1.将Word文档转换为HTML&#xff1a;mammoth.js&#xff0c;它可以将.docx文件转换为HTML 2.将HTML转换为PDF&#xff1a;使用html2pdf.js将HTML转换为PDF 如果想要相同的效果&#xff0c;也可以把前端页面直接导出转换为pdf: 运用的插件&#xff1a;html2pdf.js 后端…