ES入门十四:分词器

news2025/1/23 7:17:47

我们存储到ES中数据大致分为以下两种:

  1. 全文本,例如文章内容、通知内容
  2. 精确值,如实体Id

在对这两类值进行查询的时候,精确值类型会比较它们的二进制,其结果只有相等或者不想等。而对全文本类型进行等值比较是不太实现的,一般我们只会比较两个文本是否相似。根据上一讲的内容我们知道,要比较两个文本类型是否相似,使用相关性评分来评估的。而要得到相关性评分,我们就需要对全文本进行分词处理,然后得到统计数据才能进行评估

在es中,负责处理文本分词的是分词器,本文我们就来学习ES中分词器的组成和部分分词器的特性。

分词(Analysis)与分词器

分词是将全文本转换为一系列单词的过程,这些单词称为term或者token,而这个过程称为分词。
分词是通过**分词器(Analyzer)来实现的,**比如用于中文分词的IK分词器等。当然你也可以实现自己的分词器,例如可以简单将全文本以空格来实现分词。ES内置来一些常用的分词器,如果不能满足你的需求,你可以安装第三方的分词器或者定制化你自己的分词器。

**除了在写入的时候对数据进行分词,在对全文本进行查询的时候也需要使用相同的分词器对检索内存进行分析。例如,**查询Java Book的时候会分为java 和book两个单词,如下如所示:
image.png

分词器的组成

分词器主要由 3 部分组成。

  • Character Filter:注意对原文本进行格式处理,比如去除html标签
  • Tokenizer:按照指定规则对文本进行切分,比如按空格来切分单词,同时页负责标记出每个单词的顺序、位置以及单词在原文本中开始和结束的偏移量
  • Token Filter:对切分后的单词进行处理,如转换为小写、删除停顿词、增加同义词、词干化等

如下图就是分词器工作的流程,需要进行分词的文本依次通过Character Filter、Tokenizer、Token Filter,最后得出切分后的词项:
image.png

ES内置的分词器

为了方便用户使用,Es为用户提供了多个内置的分词器,常见的有以下8种。

  • Standard Analyzer:这个是默认的分词器,使用Unicode文本分割算法,将文本按单词切分并且转换为小写
  • Simple Analyzer:按照非字母切分并且进行小写处理
  • Stop Analyzer:与 Simple Analyzer 类似,但增加了停用词过滤(如 a、an、and、are、as、at、be、but 等)。
  • Whitespace Analyzer:使用空格对文本进行切分,并不进行小写转换
  • Pattern n Analyzer;使用正则表达式切分,默认使用 \W+ (非字符分隔)。支持小写转换和停用词删除。
  • Keyword Analyzer:不进行分词
  • Language Analyzer:提供了多种常见语言的分词器。如 Irish、Italian、Latvian 等。
  • Customer Analyzer:自定义分词器

下面我们通过讲解Standard Analyzer来进一步熟悉分词器的工作流程,但在这之前我要先介绍一个Es提供的API:_analyze。
_analyze Api是一个非常有用的工具,它可以帮助我们查看分词器是如何工作的。_analyze API 提供了 3 种方式来查看分词器是如何工作的。

  1. 使用 _analyze API 时可以直接指定 Analyzer 来进行测试,示例如下:
GET _analyze
{
  "analyzer": "standard",
  "text": "Your cluster could be accessible to anyone."
}

# 结果
{
  "tokens": [
    {
      "token": "your",
      "start_offset": 0,
      "end_offset": 4,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "cluster",
      "start_offset": 5,
      "end_offset": 12,
      "type": "<ALPHANUM>",
      "position": 1
    }
    ......
  ]
}

如上示例,在这段代码中我们可以看到它将text的内容用standard分词器进行分词,text的内容按单词进行了切分并且your转为了小写。

  1. 对指定的索引进行测试,示例如下:
# 创建和设置索引
PUT my-index
{
  "mappings": {
    "properties": {
      "my_text": {
        "type": "text",
        "analyzer": "standard"  # my_text字段使用了standard分词器
      }
    }
  }
}

GET my-index/_analyze 
{
  "field": "my_text", # 直接使用my_text字段已经设置的分词器
  "text":  "Is this déjà vu?"
}

# 结果:
{
  "tokens": [
    {
      "token": "is",
      "start_offset": 0,
      "end_offset": 2,
      "type": "<ALPHANUM>",
      "position": 0
    },
    ......
  ]
}

  1. 组合 tokenizer、filters、character filters 进行测试,示例如下:
GET _analyze 
{
  "tokenizer": "standard", # 指定一个tokenizer
  "filter":  [ "lowercase", "asciifolding" ], # 可以组合多个token filter
  # "char_filter":"html_strip", 可以指定零个Character Filter
  "text": "java app"
}

从上面的示例可以看到,tokenizer使用了standard而token filter使用了lowercase和ascillfolding来对text的内容进行切分。用户可以组合一个tokenizer、零个或者多个token filter、零个或者多个character filter。

Standard Analyzer

Standard Analyzer 是 ES 默认的分词器,它会将输入的内容按词切分,并且将切分后的词进行小写转换,默认情况下停用词(Stop Word)过滤功能是关闭的。
image.png
可以试一下下面这个例子:

GET _analyze
{
  "analyzer": "standard", # 设定分词器为 standard
  "text": "Your cluster could be accessible to anyone."
}

# 结果
{
  "tokens": [
    {
      "token": "your",
      "start_offset": 0,
      "end_offset": 4,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "cluster",
      "start_offset": 5,
      "end_offset": 12,
      "type": "<ALPHANUM>",
      "position": 1
    } 
    ......
  ]
}

如上示例,从其结果中可以看出,单词You做了小写转换,停用词be没有被去掉,并且返回结果里记录了这个单词在原文本中的开始偏移量、结束偏移以及这个词出现的位置

自定义分词器

除了使用内置的分词器外,我们还可以通过组合 Tokenizer、Filters、Character Filters 来自定义分词器。其用例如下:

PUT my-index-001
{
  "settings": {
    "analysis": {
      "char_filter": { # 自定义char_filter
        "and_char_filter": {
          "type": "mapping",
          "mappings": ["& => and"] # 将 '&' 转换为 'and'
        }
      },
      "filter": { # 自定义 filter
        "an_stop_filter": {
          "type": "stop",
          "stopwords": ["an"] # 设置 "an" 为停用词
        }
      },
      "analyzer": { # 自定义分词器为 custom_analyzer
        "custom_analyzer": {
          "type": "custom",
          # 使用内置的html标签过滤和自定义的my_char_filter
          "char_filter": ["html_strip", "and_char_filter"],
          "tokenizer": "standard",
          # 使用内置的lowercase filter和自定义的my_filter
          "filter": ["lowercase", "an_stop_filter"]
        }
      }
    }
  }
}

GET my-index-001/_analyze
{
  "analyzer": "custom_analyzer",
  "text": "Tom & Gogo bought an orange <span> at an orange shop"
}

你可以在 Kibana 中运行上述的语句并且查看结果是否符合预期,Tom 和 Gogo 将会变成小写,而 & 会转为 and,an 这个停用词和这个 html 标签将会被处理掉,但 at 不会。
ES 的内置分词器可以很方便地处理英文字符,但对于中文却并不那么好使,一般我们需要依赖第三方的分词器插件才能满足日常需求。

中文分词器

中文分词不像英文分词那样可以简单地以空格来分隔,而是要分成有含义的词汇,但相同的词汇在不同的语境下有不同的含义。社区中有很多优秀的分词器,这里列出几个日常用得比较多的。

  • analysis-icu是官方的插件,其将Lucene ICU module融入到es中。使用ICU函数库来处理提供处理Unicode的工具
  • IK:支持自定义词典和词典热更新
  • THULAC:其安装和使用官方文档中有详细的说明,本文就不再赘述了

analysis-icu分词器

analysis-icu 是官方的插件,项目在这里。ICU 的安装如下:

# 进入脚本目录,参见ES 简介和安装一节我们把es安装在ES/es_node1

# 有3个节点的需要分别进入3个节点目录进行安装 !!!!!

cd ES/es_node1

bin/elasticsearch-plugin install https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-7.13.0.zip

# 如果安装出错,并且提示你没有权限,请加上sudo:

sudo bin/elasticsearch-plugin install https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-icu/analysis-icu-7.13.0.zip

ICU 的用例如下:

POST _analyze
{  
    "analyzer": "icu_analyzer",
    "text": "Linus 在90年代开发出了linux操作系统"  
}

# 结果
{
  "tokens" : [
    ......
    {
      "token" : "开发",
      "start_offset" : 11,
      "end_offset" : 13,
      "type" : "<IDEOGRAPHIC>",
      "position" : 4
    },
    {
      "token" : "出了",
      "start_offset" : 13,
      "end_offset" : 15,
      "type" : "<IDEOGRAPHIC>",
      "position" : 5
    },
    {
      "token" : "linux",
      "start_offset" : 15,
      "end_offset" : 20,
      "type" : "<ALPHANUM>",
      "position" : 6
    }
    ......
  ]
}

通过在 Kibana 上运行上述查询语句,可以看到结果与 Standard Analyzer 是不一样的,同样你可以将得出的结果和下面的 IK 分词器做一下对比,看看哪款分词器更适合你的业务。更详细的 ICU 使用文档可以查看:ICU 文档

IK分词器

IK 的算法是基于词典的,其支持自定义词典和词典热更新。下面来安装 IK 分词器插件:

# 有3个节点的需要分别进入3个节点目录进行安装 !!!!!

cd ES/es_node1

# 如果因为没有权限而安装失败的话,使用sudo ./bin/elasticsearch-plugin install url 来安装

./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.13.0/elasticsearch-analysis-ik-7.13.0.zip

在每个节点执行完上述指令后,需要重启服务才能使插件生效。重启后,可以在 Kibana 中测试一下 IK 中文分词器的效果了。

POST _analyze
{  
    "analyzer": "ik_max_word",
    "text": "Linus 在90年代开发出了linux操作系统"  
}

POST _analyze
{  
    "analyzer": "ik_smart",
    "text": "Linus 在90年代开发出了linux操作系统"  
}

如上示例可以看到,IK 有两种模式:ik_max_word 和 ik_smart,它们的区别可总结为如下(以下是 IK 项目的原文)。

  • ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、人、民、共和国、共和、和、国国、国歌”,会穷尽各种可能的组合,适合 Term Query。
  • ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国、国歌”,适合 Phrase 查询。

关于 IK 分词器插件更详细的使用信息,你可以参考 IK 项目的文档。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1576216.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CVE漏洞是什么,如何对其进行针对性的防护

CVE&#xff08;Common Vulnerabilities and Exposures&#xff09;漏洞是一个网安技术术语&#xff0c;用于描述和标识信息安全领域的已知漏洞和安全风险。CVE是一个公开的列表或数据库&#xff0c;它为各种公开知晓的信息安全漏洞和风险提供了标准化的名称。 每个CVE标识符都…

Java-类型转换

Java数据类型转换的规则掌握后&#xff0c;将使我们对以后的学习事半功倍&#xff0c;下面是我列出的一些重点。 类型转换 由于Java是强类型语言&#xff0c;所以要进行有些运算的时候&#xff0c;需要用到类型转换。底到高依次是&#xff1a;byte,short,char->int->lo…

ThinkPHP审计(2) Thinkphp反序列化链5.1.X原理分析从0编写POC

ThinkPHP审计(2) Thinkphp反序列化链子5.1.X原理分析&从0编写POC 文章目录 ThinkPHP审计(2) Thinkphp反序列化链子5.1.X原理分析&从0编写POC动态调试环境配置Thinkphp反序列化链5.1.X原理分析一.实现任意文件删除二.实现任意命令执行真正的难点 Thinkphp反序列化链5.1.…

openGauss学习笔记-257 openGauss性能调优-使用Plan Hint进行调优-Custom Plan和Generic Plan选择的Hint

文章目录 openGauss学习笔记-257 openGauss性能调优-使用Plan Hint进行调优-Custom Plan和Generic Plan选择的Hint257.1 功能描述257.2 语法格式257.3 示例 openGauss学习笔记-257 openGauss性能调优-使用Plan Hint进行调优-Custom Plan和Generic Plan选择的Hint 257.1 功能描…

【MYSQL之进阶篇】视图、存储过程、存储函数以及触发器

&#x1f525;作者主页&#xff1a;小林同学的学习笔录 &#x1f525;mysql专栏&#xff1a;小林同学的专栏 1.视图 1.1 定义 视图是MySQL数据库中的虚拟表&#xff0c;它基于一个或多个实际表的查询结果。视图提供了一种简单的 方法来封装和重用复杂的查询&#xff0c;同时…

Prometheus-Grafana基础篇安装绘图

首先Prometheus安装 1、下载 https://prometheus.io/download/ 官网路径可以去这儿下载 2、如图&#xff1a; 3.解压&#xff1a; tar -xf prometheus-2.6.1.linux-amd64 cd prometheus-2.6.1.linux-amd64 4.配置文件说明&#xff1a; vim prometheus.yml 5.启动Promethe…

【蓝桥杯嵌入式】12届程序题刷题记录及反思

一、题目解析 按键短按LCD显示两个界面LED指示灯PWM脉冲输出 二、led控制 控制两个led灯&#xff0c;两种状态 //led void led_set(uint8_t led_dis) {HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOC,led_dis << 8,GPIO_PIN_RESET);HAL…

Java常用API_正则表达式_分组——捕获分组与非捕获分组介绍与练习

在正则表达式中&#xff0c;从左到右第一个左括号确定为第一组&#xff0c;继续往右看再有左括号它表示的组数就加一。我们可以在正则表达式中使用 \\组数 的方法表示第几组&#xff0c;如\\1表示第一组的内容。 1.捕获分组 捕获分组就是把这一组的数据捕获出来&#xff0c;后…

何为网络协议?一图知晓网络过程。

网络协议就是计算机之间沟通的语言 为了有效地交流&#xff0c;计算机之间需要一种共同的规则或协议&#xff0c; 就像我们和老外沟通之前&#xff0c;要先商量好用哪种语言&#xff0c; 要么大家都说中文&#xff0c;要么大家都说英语&#xff0c;这才能有效地沟通。 网络协…

git bash上传文件至github仓库

Linux运维工具-ywtool 目录 一.访问github二.新建仓库1.点击自己头像2.选择"your repositories"3.点击"New"4.创建新仓库 三.通过git bash软件上传文件1.提示2.打开git bash软件3.切换到本地仓库目录4.配置github的用户名和邮箱信息5.生成SSH Key6.github添…

【使用flex两端对齐加margin-right】

解决办法众多&#xff1a;https://cloud.tencent.com/developer/article/1516801 <div class"job_tabs_content"><div class"job_tab_item"></div><div class"job_tab_item"></div><div class"job_tab_i…

c++的学习之路:15、list(2)

本章主要是讲模拟实现list&#xff0c;文章末附上代码。 目录 一、创建思路 二、构造函数 三、迭代器 四、增删 五、代码 一、创建思路 如下方代码&#xff0c;链表是由一块一块不连续的空间组成的&#xff0c;所以这里写了三个模板&#xff0c;一个是节点&#xff0c;一…

Linux IO的奥秘:深入探索数据流动的魔法

Linux I/O&#xff08;输入/输出&#xff09;系统是其核心功能之一&#xff0c;负责处理数据在系统内部及与外界之间的流动。为了优化这一流程&#xff0c;Linux进行了一系列努力和抽象化&#xff0c;以提高效率、灵活性和易用性。&#x1f680; 1. 统一的设备模型 Linux将所…

SpringCloud Alibaba Sentinel 实现熔断功能

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅&#xff0c;从传统的模块之间调用&#xff0c;一步步的升级为 SpringCloud 模块之间的调用&#xff0c;此篇文章为第十六篇&#xff0c;即使用 Sentinel 实现熔断功能。 二、 Ribbon 系列 首先我们新建两个服务的提供者…

2024单品正价起号,直播素材投流选品,【选品课】+【投流课】+【素材课】+【卡首屏】

课程下载&#xff1a;https://download.csdn.net/download/m0_66047725/89064168 更多资源下载&#xff1a;关注我。 课程内容: 01 01 1.如何养账号过风控,mp4 01 1.如何搭建一条计划(1)..mp4 02 1.如何搭建一条计划(2)..mp4 02 02 2.单品起号方案如何选择,mp4 03 2.-比…

Linux -- 字符设备驱动--LED的驱动开发(初级框架)

驱动框架一阶段 我们怎样去点亮一个 LED 呢&#xff1f;分为三步&#xff1a; 看原理图确定引脚&#xff0c;确定引脚输出什么电平才能点亮/熄灭 LED 看主芯片手册&#xff0c;确定寄存器操作方法&#xff1a;哪些寄存器&#xff1f;哪些位&#xff1f;地址是&#xff1f; 编…

每天五分钟掌握深度学习框架pytorch:本专栏说明

专栏大纲 专栏计划更新章节在100章左右&#xff0c;之后还会不断更新&#xff0c;都会配备代码实现。以下是专栏大纲 部分代码实现 代码获取 为了方便用户浏览代码&#xff0c;本专栏将代码同步更新到github中&#xff0c;所有用户可以读完专栏内容和代码解析之后&#xff0c…

go语言实现无头单向链表

什么是无头单向链表 无头单向链表是一种线性数据结构&#xff0c;它的每个元素都是一个节点&#xff0c;每个节点都有一个指向下一个节点的指针。"无头"意味着这个链表没有一个特殊的头节点&#xff0c;链表的第一个节点就是链表的头。 优点&#xff1a; 动态大小&…

三种算法实例(二分查找算法、插入排序算法、贪心算法)

当我们听到“算法”这个词时&#xff0c;很自然地会想到数学。然而实际上&#xff0c;许多算法并不涉及复杂数学&#xff0c;而是更多地依赖基本逻辑&#xff0c;这些逻辑在我们的日常生活中处处可见。 在正式探讨算法之前&#xff0c;有一个有趣的事实值得分享&#xff1a;你…

X64 基础(1)

X64 汇编 生成依赖项->生成自定义 勾选汇编选项 新建ASM文件 .codeaddl proc add rcx,rdx mov rax,rcx retaddl endpend项目类型选择汇编 在头文件中导出 EXTERN_C ULONG64 addl(ULONG64 x, ULONG64 y);然后就可以正常调用了&#xff0c;不能直接内联 X64内存 X64跟…