(6)elasticsearch的分词器

news/2024/9/15 22:22:35/

1 文档规范化(normalization)

是为了提高召回率。

停用词 、时态转换、大小写、同义词、语气词。

以下的doc1\doc2,经过normalization之后,在搜索的时候是可以匹配到这两个doc。

在这里插入图片描述

我们可以看到,normalization就是把一些词 变成 通用的词

#normalization
GET _analyze
{"text": "Mr. Ma is an excellent teacher","analyzer": "standard"
}
#结果:Mr-》mr。Ma-》ma。等等。

2 字符过滤器(character filter)

分词之前的预处理,过滤无用字符

  • HTML Strip Character Filter:html_strip。过滤掉html标签的。
    • 参数:escaped_tags 需要保留的html标签
  • Mapping Character Filter:type是mapping。可以将一些词替换成xxx。
  • Pattern Replace Character Filter:type是pattern_replace。正则替换。
#character filter
##HTML Strip Character Filter
DELETE my_index
#创建分词器my_analyzer 和 过滤器my_char_filter
#把html标签过滤掉,保留a标签
PUT my_index
{"settings": {"analysis": {"char_filter": {"my_char_filter":{"type":"html_strip","escaped_tags":["a"]}},"analyzer": {"my_analyzer":{"tokenizer":"keyword","char_filter":["my_char_filter"]}}}}
}
GET my_index/_analyze
{"analyzer": "my_analyzer","text": "<p>I&apos;m so <a>happy</a>!</p>"
}
#结果:I'm so <a>happy</a>!##Mapping Character Filter 
DELETE my_index
#把一些词替换成*
PUT my_index
{"settings": {"analysis": {"char_filter": {"my_char_filter":{"type":"mapping","mappings":["滚 => *","垃 => *","圾 => *"]}},"analyzer": {"my_analyzer":{"tokenizer":"keyword","char_filter":["my_char_filter"]}}}}
}
GET my_index/_analyze
{"analyzer": "my_analyzer","text": "你就是个垃圾!滚"
}
#结果:你就是个**!*##Pattern Replace Character Filter 
#17611001200
DELETE my_index
#正则替换
PUT my_index
{"settings": {"analysis": {"char_filter": {"my_char_filter":{"type":"pattern_replace","pattern":"(\\d{3})\\d{4}(\\d{4})","replacement":"$1****$2"}},"analyzer": {"my_analyzer":{"tokenizer":"keyword","char_filter":["my_char_filter"]}}}}
}
GET my_index/_analyze
{"analyzer": "my_analyzer","text": "您的手机号是17611001200"
}
#结果:您的手机号是176****1200

3 令牌过滤器(token filter)

停用词、时态转换、大小写转换、同义词转换、语气词处理等。比如:has=>have him=>he apples=>apple the/oh/a=>干掉。

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/analysis-synonym-tokenfilter.html

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/analysis-keyword-marker-tokenfilter.html

(这里需要用到ik分词器)

在elasticsearch-7.10.0\config目录下新建analysis目录,新建synonym.txt,内容为

蒙丢丢 ==> 蒙
大G ==> 大
霸道 ==> 霸
daG ==> 大哥
#token filter
DELETE test_index
#在elasticsearch-7.10.0\config目录下新建analysis目录,新建synonym.txt
#创建了个同义词转换,使用的是文件
PUT /test_index
{"settings": {"analysis": {"filter": {"my_synonym": {"type": "synonym_graph","synonyms_path": "analysis/synonym.txt"}},"analyzer": {"my_analyzer": {"tokenizer": "ik_max_word","filter": [ "my_synonym" ]}}}}
}
GET test_index/_analyze
{"analyzer": "my_analyzer","text": ["蒙丢丢,大G,霸道,daG"]
}
#结果:蒙\大\霸\大哥
GET test_index/_analyze
{"analyzer": "ik_max_word","text": ["奔驰G级"]
}
#结果:拆分成了 奔驰、g、级 词项DELETE test_index
#创建了个同义词转换,没有使用文件
#赵,钱,孙,李 的同义词都是 吴
PUT /test_index
{"settings": {"analysis": {"filter": {"my_synonym": {"type": "synonym","synonyms": ["赵,钱,孙,李=>吴","周=>王"]}},"analyzer": {"my_analyzer": {"tokenizer": "standard","filter": [ "my_synonym" ]}}}}
}
GET test_index/_analyze
{"analyzer": "my_analyzer","text": ["赵,钱,孙,李","周"]
}
#结果:吴、王#大小写转换
GET test_index/_analyze
{"tokenizer": "standard","filter": ["lowercase"], "text": ["AASD ASDA SDASD ASDASD"]
}
#结果:都变成了小写
GET test_index/_analyze
{"tokenizer": "standard","filter": ["uppercase"], "text": ["asdasd asd asg dsfg gfhjsdf asfdg g"]
}
#结果:都变成了大写
#复杂点的,使用脚本的:长度小于5的变成大写
GET test_index/_analyze
{"tokenizer": "standard","filter": {"type": "condition","filter":"uppercase","script": {"source": "token.getTerm().length() < 5"}}, "text": ["asdasd asd asg dsfg gfhjsdf asfdg g"]
}#停用词
DELETE test_index
#把me\you停用了
PUT /test_index
{"settings": {"analysis": {"analyzer": {"my_analyzer": {"type": "standard","stopwords":["me","you"]}}}}
}
GET test_index/_analyze
{"analyzer": "my_analyzer", "text": ["Teacher me and you in the china"]
}
#结果里边没有me\you

4 分词器(tokenizer)

主要是将document切词,切割点。

https://www.elastic.co/guide/en/elasticsearch/reference/7.10/analysis-standard-tokenizer.html

#分词器 tokenizer
#standard以空格进行切词的,对英文支持比较好
GET test_index/_analyze
{"analyzer": "standard", "text": ["Teacher me and you in the china"]
}
#结果:各个单词
GET test_index/_analyze
{"tokenizer": "ik_max_word","text": ["我爱北京天安门","天安门上太阳升"]
}
#结果:把一些特定的词拆分,比较符合中文的习惯

5 常见分词器:

  • standard analyzer:默认分词器,中文支持的不理想,会逐字拆分。
  • pattern tokenizer:以正则匹配分隔符,把文本拆分成若干词项。
  • simple pattern tokenizer:以正则匹配词项,速度比pattern tokenizer快。
  • whitespace analyzer:以空白符分隔 Tim_cookie

6 自定义分词器:custom analyzer

  • char_filter:内置或自定义字符过滤器 。
  • token filter:内置或自定义token filter 。
  • tokenizer:内置或自定义分词器。
#自定义分词器
DELETE custom_analysis
PUT custom_analysis
{"settings": {"analysis": {"char_filter": {"my_char_filter": {"type": "mapping","mappings": ["& => and","| => or"]},"html_strip_char_filter":{"type":"html_strip","escaped_tags":["a"]}},"filter": {"my_stopword": {"type": "stop","stopwords": ["is","in","the","a","at","for"]}},"tokenizer": {"my_tokenizer": {"type": "pattern","pattern": "[ ,.!?]"}}, "analyzer": {"my_analyzer":{"type":"custom","char_filter":["my_char_filter","html_strip_char_filter"],"filter":["my_stopword","lowercase"],"tokenizer":"my_tokenizer"}}}}
}GET custom_analysis/_analyze
{"analyzer": "my_analyzer","text": ["What is ,<a>as.df</a>  ss<div> in ? &</div> | is ! in the a at for "]
}

7 中文分词器:ik分词

自定义词库和热更新可以参考它的github主页介绍。

  1. 安装和部署

    • ik下载地址:https://github.com/medcl/elasticsearch-analysis-ik
    • Github加速器:https://github.com/fhefh2015/Fast-GitHub
    • 创建插件文件夹 cd your-es-root/plugins/ && mkdir ik
    • 将插件解压缩到文件夹 your-es-root/plugins/ik
    • 重新启动es
  2. IK文件描述

    • IKAnalyzer.cfg.xml:IK分词配置文件
  • 主词库:main.dic
    • 英文停用词:stopword.dic,不会建立在倒排索引中
    • 特殊词库:
      • quantifier.dic:特殊词库:计量单位等
      • suffix.dic:特殊词库:行政单位
      • surname.dic:特殊词库:百家姓
      • preposition:特殊词库:语气词
    • 自定义词库:网络词汇、流行词、自造词等
自定义词库过程:
1、在elasticsearch-7.10.0\plugins\ik\config下创建custom目录,创建文件wxd_extra.dic、wxd_extra2.dic
2、文件内容
#wxd_extra.dic
蒙丢丢
#wxd_extra2.dic
渣男
渣女
3、修改配置文件IKAnalyzer.cfg.xml
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">custom\wxd_extra.dic;custom\wxd_extra2.dic</entry>
3、重启es,再次查询
GET custom_analysis/_analyze
{"analyzer": "ik_max_word","text": ["蒙丢丢","渣男","渣女"]
}
#添加自定义词库之前结果:蒙、丢、丢、渣、男、渣、女
#添加自定义词库之后结果:蒙丢丢、渣男、渣女
  1. ik提供的两种analyzer:

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

    8 ik热更新

    1. 远程词库文件
      1. 优点:上手简单
      2. 缺点:
        1. 词库的管理不方便,要操作直接操作磁盘文件,检索页很麻烦
        2. 文件的读写没有专门的优化性能不好
        3. 多一层接口调用和网络传输
    2. ik访问数据库
      1. MySQL驱动版本兼容性
        1. https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-versions.html
        2. https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-versions.html
      2. 驱动下载地址
        1. https://mvnrepository.com/artifact/mysql/mysql-connector-java

8 ik热更新

目前该插件支持热更新 IK 分词,通过上文在 IK 配置文件中提到的如下配置

 	<!--用户可以在这里配置远程扩展字典 --><entry key="remote_ext_dict">location</entry><!--用户可以在这里配置远程扩展停止词字典--><entry key="remote_ext_stopwords">location</entry>

其中 location 是指一个 url,比如 http://yoursite.com/getCustomDict,该请求只需满足以下两点即可完成分词热更新。

  1. 该 http 请求需要返回两个头部(header),一个是 Last-Modified,一个是 ETag,这两者都是字符串类型,只要有一个发生变化,该插件就会去抓取新的分词进而更新词库。
  2. 该 http 请求返回的内容格式是一行一个分词,换行符用 \n 即可。

满足上面两点要求就可以实现热更新分词了,不需要重启 ES 实例。

可以将需自动更新的热词放在一个 UTF-8 编码的 .txt 文件里,放在 nginx 或其他简易 http server 下,当 .txt 文件修改时,http server 会在客户端请求该文件时自动返回相应的 Last-Modified 和 ETag。可以另外做一个工具来从业务系统提取相关词汇,并更新这个 .txt 文件。

基于远程词库的热更新

  1. 优点:上手简单
  2. 缺点:
    1. 词库的管理不方便,要操作直接操作磁盘文件,检索页很麻烦
    2. 文件的读写没有专门的优化性能不好
    3. 多一层接口调用和网络传输

需要:一个普通的springboot项目(controller)+ 词库文件

@RestController
@RequestMapping(value = "/api")
public class HomeController {@RequestMapping(value = "hotWord")public void hotword(HttpServletResponse response, Integer wordlib) throws IOException {File file = new File(wordlib == 1 ? "./files/wxd_extend.dic" : "./files/wxd_stopword.dic");FileInputStream fis = new FileInputStream(file);byte[] buffer = new byte[(int) file.length()];response.setContentType("text/plain;charset=utf-8");response.setHeader("Last-Modified", String.valueOf(buffer.length));response.setHeader("ETag", String.valueOf(buffer.length));int offset = 0;while (fis.read(buffer, offset, buffer.length - offset) != -1) {}OutputStream out = response.getOutputStream();out.write(buffer);out.flush();fis.close();}
}

在springboot项目的目录下新建files目录,里边分别有两个文件wxd_extend.dic、wxd_stopword.dic,此时都是空的

修改配置文件IKAnalyzer.cfg.xml

<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">http://localhost:9081/api/hotWord?wordlib=1</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<entry key="remote_ext_stopwords">http://localhost:9081/api/hotWord?wordlib=2</entry>

在修改了wxd_extend.dic、wxd_stopword.dic之后,es会自动去请求远程字典的地址。

#文件内容都为空的时候
GET custom_analysis/_analyze
{"analyzer": "ik_max_word","text": ["张明","太阳"]
}
#结果:张、明、太阳#wxd_extend.dic中添加张明,es会加载文件内容,之后,再测测试:张、明  变成了 张明
#wxd_stopword.dic中添加太阳,es会加载文件内容,之后,再测测试:太阳 不再显示了

在这里插入图片描述

=非常重要的注意===文件一定要是UTF-8 编码的。

在这里插入图片描述

基于mysql的热更新

  1. MySQL驱动版本兼容性
    1. https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-versions.html
    2. https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-versions.html
  2. 驱动下载地址
    1. https://mvnrepository.com/artifact/mysql/mysql-connector-java

需要:ik的源码+ mysql

1、下载ik的源码,https://github.com/medcl/elasticsearch-analysis-ik/releases

在这里插入图片描述

2、pom中添加mysql连接,在config文件里边创建一个jdbc配置

        <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency>
#jdbc-reload.properties
jdbc.url=jdbc:mysql://localhost:3306/es_ik_use?serverTimezone=UTC
jdbc.user=root
jdbc.password=123456
jdbc.reload.sql=select word from ik_extword
jdbc.reload.stopword.sql=select stopword as word from ik_stopword
jdbc.reload.interval=1000

根据org.wltea.analyzer.dic.Dictionary 模仿写出通过jdbc的加载热数据

根据org.wltea.analyzer.dic.Monitor模仿写出jdbc的monitor

3、打包

把target/releases下的zip包,复制到elasticsearch-7.10.0\plugins下,解压,重新命名为ik。

再次检查jdbc-reload.properties的内容是否正确。

之后,把mysql的jar包放到ik文件里边。

在这里插入图片描述

4、启动es,测试


http://www.ppmy.cn/news/54423.html

相关文章

Docker安装Redis(普通安装+在线安装+离线安装)

文章目录 Redis概述一、磁盘安装1.1 安装环境1.2 安装步骤1.3 服务器启停命令 二、docker安装1.在线安装2.离线安装 总结 Redis概述 Redis&#xff0c;英文全称是Remote Dictionary Server&#xff08;远程字典服务&#xff09;&#xff0c;是一个开源的使用ANSI C语言编写、支…

RK3568平台开发系列讲解(驱动基础篇)IO 模型的分类

🚀返回专栏总目录 文章目录 一、阻塞 IO二、非阻塞 IO三、IO 多路复用四、信号驱动五、异步 IO沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将针对IO模型进行分类。 假设有这样一个场景,从磁盘中循环读取 100M 的数据并处理,磁盘读取 100M 需要花费 20 秒的…

消费端和产业端的融合,主要是依靠需求与供给的无缝对接来实现

如果我们要寻找直播带货的未来发展路径的话&#xff0c;如何找到直播带货回归产业的正确的方式和方法&#xff0c;如何让直播带货与产业端产生更多的联系&#xff0c;发挥直播带货与消费者无缝对接的优势&#xff0c;让消费者的需求第一时间传递给产业端&#xff0c;更好地赋能…

【华为HCIP | 高级网络工程师】刷题日记(1)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生&#xff0c;讨厌编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;落. &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️ 零基础…

〖ChatGPT实践指南 - 零基础扫盲篇⑨〗- OpenAI API 的数据使用政策以及使用限制

文章目录 ⭐ OpenAI API 数据使用政策⭐ 关于 API 数据的一些通用型问题⭐ OpenAI API 数据使用政策的限制 该章节为各位小伙伴介绍以下 OpenAI 的API 数据使用政策&#xff0c;这部分的内容是 OpenAI 官方为我们提供的一份文档&#xff0c;这份文档说明了官方在为我们提供的AP…

【计算机网络 - 第二章】应用层(更新中)

目录 一、应用层协议原理 1、网络应用程序体系结构 &#xff08;1&#xff09;客户/服务器模型&#xff08;C/S&#xff09; &#xff08;2&#xff09;P2P模型&#xff08;Peer-to-Peer&#xff09; 2、进程通信 &#xff08;1&#xff09;客户和服务器进程 &#xff0…

Qt音视频开发42-网络推流(视频推流/本地摄像头推流/桌面推流/网络摄像头转发推流等)

一、前言 上次实现的文件推流&#xff0c;尽管优点很多&#xff0c;但是只能对现在存在的生成好的音视频文件推流&#xff0c;而现在更多的场景是需要将实时的视频流重新推流分发&#xff0c;用户在很多设备比如手机/平板/网页/电脑/服务器上观看&#xff0c;这样就可以很方便…

Javaweb | 转发、重定向

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 转发 转发与页面跳转 转发 转发的作用在服务器端&#xff0c;将请求发送给服务器上的其他资源&#xff0c;以共同完成一次请求的处理 页面跳转 使用forward跳转时&am…

Mybatis-Flex快速入门教程

目录 一、Mybatis-Flex是什么&#xff1f; 二、Mybatis-Flex的有什么特点&#xff1f; 三、Mybatis-Flex和同类框架对比 四、Mybatis-Flex支持的数据库类型 五、快速入门 &#xff08;1&#xff09;引入依赖 &#xff08;2&#xff09;创建数据库 &#xff08;3&#…

java获取类结构信息

package com.hspedu.reflection;import org.junit.jupiter.api.Test;import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;/*** author 韩顺平* version 1.0* 演示如何通过反射获…

Java IO流第一章

Java IO流第一章 &#xff08;一&#xff09;简介 本文主要是从最基础的BIO式通信开始介绍到NIO , AIO&#xff0c;读者可以清晰的了解到阻塞、同步、异步的现象、概念和特征以及优缺点。 通信技术整体解决的问题 局域网内的通信要求。多系统间的底层消息传递机制。高并发下…

【C++】了解设计模式、 stackqueue的使用与模拟实现

文章目录 1.设计模式2.stack1.stack的使用1.stack的结构2.stack的接口 2.stack的模拟实现1.stack的结构2.接口实现 3.queue1.queue的使用1.queue的结构3.queue的接口 2.queue的模拟实现1.queue的结构2.接口实现 4.了解deque1.deque的原理介绍2.deque的底层结构3.deque的迭代器设…

【C++】STL——list深度剖析 及 模拟实现

文章目录 前言1. list的介绍及使用1.1 list的介绍1.2 list的使用遍历插入删除数据Operations迭代器的功能分类list 的sort性能测试 2. list的模拟实现2.1 STL_list源码浏览2.2 基本结构实现2.3 思考&#xff1a;list迭代器是否可以用原生指针2.4 list迭代器的实现&#xff08;重…

C/C++基础知识

专栏&#xff1a;C/C 个人主页&#xff1a; C/C基础知识 前言C关键字(C98)命名空间命名空间的定义正常的命名空间的定义如何使用命名空间 命名空间可以嵌套同一个工程中允许存在多个相同名称的命名空间&#xff0c;编译器最后会合成同一个命名空间中(一个工程中的.h文件和test.…

【LLM】LLaMA简介:一个650亿参数的基础大型语言模型

LLaMA简介&#xff1a;一个650亿参数的基础大型语言模型 PaperSetup其他资料 作为 Meta 对开放科学承诺的一部分&#xff0c;今天我们将公开发布 LLaMA (大型语言模型 Meta AI) &#xff0c;这是一个最先进的大型语言基础模型&#xff0c;旨在帮助研究人员推进他们在人工智能这…

ApplicationContextAware接口

一、ApplicationContextAware接口的基本介绍 public interface ApplicationContextAware extends Aware {void setApplicationContext(ApplicationContext applicationContext) throws BeansException;}在Spring/SpringMVC中&#xff0c;我们拿到IOC容器无非有三种方式&#x…

Cortex-A7中断详解(二)

CP15协处理器 CP15协处理器一般用于存储系统管理&#xff0c;但是在中断中也会使用到&#xff0c;CP15协处理器一共有16个32位寄存器。CP15协处理器的访问通过以下指令完成&#xff1a; MRC&#xff1a;将CP15协处理器中的寄存器数据读到ARM寄存器中。MCR&#xff1a;将ARM寄…

Java阶段二Day12

Java阶段二Day12 文章目录 Java阶段二Day12JDBC核心接口JDBC连接的基本流程实现DDL实现DML实现DQLPreparedStatement V20DBUtilUserController 连接池 JDBC JDBC Java数据库连接 Java Database Connectivity&#xff0c;是java官方提供的一套结构&#xff0c;用于连接DBMS并进…

结构体指针、数组指针和结构体数组指针

结构体指针 首先让我们定义结构体&#xff1a; struct stu { char name[20]; long number; float score[4]; }; 再定义指向结构体类型变量的指针变量&#xff1a; struct stu *student; /*定义结构体类型指针*/ student malloc(sizeof(struct stu)); /*为指针变量分…

8个免费的PNG素材网站推荐

很多设计小白都不知道什么是PNG。事实上&#xff0c;PNG是一种支持透明度的图像格式。当你想在设计中将图像与背景或文本混合时&#xff0c;它就会派上用场。 如果你没有时间为你正在处理的设计创建透明的PNG图像&#xff0c;你也可以使用我收集的PNG素材网站&#xff0c;以便…