什么是分词器
我们上一篇文章讲过倒排索引,比如我们搜 明月 ,可能会根据倒排索引 查到静夜思 这篇古诗,对吧,这里面的明月 低头 月光 ,就是分词器给我们分的词,我的理解就是,我们通过分词器给某篇文章打上了分词的tag ,然后根据tag 可以找到对应的标题,比如 新手机 华为,如果没有分词的话,我们查找 新手机华为 可能 华为新手机 就不会被搜索到,因为顺序的问题。
分词器的组成
- character filter(字符过滤器)
在对一段文本分词之前,要先清洗一遍原始数据吧,比如html标签,什么加黑加粗加长加大中划线下划线啥的,其实我要的就是 里面的 一个词,比如我是一个帅哥啊其实我只需要拿到 我很帅 三个字 给分词器就行了 - 分词器 就是 tokenizers
字符串过滤器把内容【我是一个帅哥啊】给分词器,分词器 就开始分词,比如分成了
我
是
一个
帅哥
啊
但是这里面有一些词并不是关键词,你拿这个词搜索也没有意义,比如 你想搜 我感冒了怎么办啊,为了让搜索更高效,让用户看起来更专业,我们拿到的关键词 应该是
感冒
怎么办
而不是 怎么办啊 或者啊,所以需要对分词之后的结果再进行过滤,这个时候就要用到分词过滤器
- token filers 就是 分词过滤器,完成对无用词的过滤
Elastic 默认支持九种不同的分词模式
-
stardard(过滤标点符号)
在这里插入图片描述 -
simple (过滤标点符号和数字,只剩下字母了)
在这里插入图片描述 -
whitespace (空格分词,不过滤内容)
在这里插入图片描述 -
stop(过滤标点符号,数字,过滤语气词,停顿词)
[图片上传失败...(image-a8ee4f-1637325715209)] -
keyword (将内容作为一个整体,不做任何处理,所以这也是为什么keyword 用于精准匹配)
在这里插入图片描述 -
patter(正则匹配,参考java的正则匹配规则)
在该栗子中,只过滤数字
在这里插入图片描述 -
fingerprint(转小写 去重 过滤停止词,排序)
在这里插入图片描述 -
支持30多种常见语言的分词器(没有中文)
-
支持自定义分词器
IK分词器
- 此处我们再解释一遍为什么要用分词,如果不用分词,我们其实也可以搜素,比如下面这个栗子,我搜索华为的时候,我爱中华的文档也被搜索了出来,我显然不是我要的,但是为什么会出现这种取情况呢?我们看中文返回的分词是什么
我们发现es对汉字默认是单个拆分的,你搜索华为,本来搜索的是华为相关的条目,单个拆分之后 ,就会把包含华和为两个字的都查找出来,这明显不是我们想要的,所以我们需要分词来达到更精准的匹配
-
ElasticSearch 对于英文分词天生就有了,因为老外生来就用外语,那么中文怎么办呢?IK分词器在2006年推出了1.0版本。
IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。被一个叫medcl(曾勇 elastic开发工程师与布道师,elasticsearch开源社区负责人,2015年加入elastic)的人集成到了elasticsearch中, 并支持自定义字。
IK分词器的安装github上面搜索https://github.com/medcl/elasticsearch-analysis-ik即可,注意版本一致,一定要去github 或者官方网站下载包,博主被第三方的包坑了两三个小时 -
装过ik 分词之后我们再查看
- 在这里插入图片描述
-
但是,此时你搜索华为 是搜索不出来的,因为在创建文档的时候就没有 对 我爱华为 建立 华为的分词索引,我们删除重新创建
在这里插入图片描述
搜索华为的时候 我爱中华 条目没有出现,只找到了一条我爱华为,记住,文档在创建的时候生成倒排索引,所以我们在创建文档的时候最好是先 勾勒出来你需要的数据模型,根据模型选择数据字段的类型,合适的分词,有了合适的结构才会有合适的索引,有了合适的索引才会提供合适发服务。之前我见有朋友没有mapping就插入数据,其实这个时候系统也动态生成了mapping ,但是这个maping 不一定符合你的要求。比如咱们刚才的分词,你创建索引的时候就是 按照 单个字 创立的索引,那么这个时候你搜索 华为 作为一个词去匹配,就会匹配不到。
[图片上传失败...(image-a21413-1637325715209)]
IK分词器的相关配置
- 我们看一下目录
[elastic@localhost config]$ ls
extra_main.dic extra_single_word.dic extra_single_word_full.dic extra_single_word_low_freq.dic extra_stopword.dic IKAnalyzer.cfg.xml main.dic preposition.dic quantifier.dic stopword.dic suffix.dic surname.dic
[elastic@localhost config]$ pwd
/home/elastic/elasticsearch2/plugins/ik/config
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">dic/hehe.dic;dic/haha.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典 比如 啊 呢 哦 无效词 -->
<entry key="ext_stopwords">dic/stop.dic</entry>
<!--用户可以在这里配置远程扩展字典 配置自己的远程扩展词 -->
<entry key="remote_ext_dict">http://m.dic.cn/ext.txt</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">http://m.dic.cn/stop.txt</entry> -->
</properties>
- 这里可以简单举个栗子看一下,比如 香菇蓝瘦,我们先来看一下
[图片上传失败...(image-9bdf6d-1637325715209)] - 我现在来配置一下文件,使用远程扩展词库(注意,如果修改或者新增了远程词库的地址,则需要重启,如果地址没变,只是进行了补充,则无需重启)
- 看一下我的远程地址(注意,为了避免浏览器访问txt 乱码,在nginx的server里面加上
charset 'utf-8';
)
在这里插入图片描述
我的配置文件如下,配置了一个远程扩展词典
<?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"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">https://0e2d-222-129-5-131.ngrok.io/ext.txt</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
在这里插入图片描述
-
我在远程词典添加一个词 技术小虫
在这里插入图片描述
main.dic
ik原生内置的中文词库,总共有27万多条,只要是这些单词,都会被分在一起
quantifier.dic
放了一些单位相关的词
suffix.dic
放了一些后缀
surname.dic
中国的姓氏
stopword.dic
英文停用词
网友评论