关键词:
什么是分词
分词就是指将一个文本转化成一系列单词的过程,也叫文本分析,在Elasticsearch中称之为Analysis。
举例:我是中国人 --> 我/是/中国人
结果:
"tokens": [ "token": "hello", "start_offset": 0, "end_offset": 5, "type": "<ALPHANUM>", "position": 0 , "token": "world", "start_offset": 6, "end_offset": 11, "type": "<ALPHANUM>", "position": 1 ]
在结果中不仅可以看出分词的结果,还返回了该词在文本中的位置。
中文分词
中文分词的难点在于,在汉语中没有明显的词汇分界点,如在英语中,空格可以作为分隔符,如果分隔不正确就会造成歧义。
如:
我/爱/炒肉丝
我/爱/炒/肉丝
常用中文分词器,IK、jieba、THULAC等,推荐使用IK分词器。
K Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出了3个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。新版本的IK Analyzer 3.0则发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。
采用了特有的“正向迭代最细粒度切分算法“,具有80万字/秒的高速处理能力 采用了多子处理器分析模式,支持:英文字母(IP地址、Email、URL)、数字(日期,常用中文数量词,罗马数字,科学计数法),中文词汇(姓名、地名处理)等分词处理。 优化的词典存储,更小的内存占用
IK分词器 Elasticsearch插件地址:https://github.com/medcl/elasticsearch-analysis-ik
[root@dalianpai ~]# docker run -p 9200:9200 -d -v /root/ik:/usr/share/elasticsearch/plugins/ik --name elasticsearch 3fd2f723b598 8378a1865408d30a279f9e057115cf4e68cfc4360fa2fe3866072ea9b820a27f [root@dalianpai ~]# docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8378a1865408 3fd2f723b598 "/docker-entrypoin..." 3 seconds ago Up 2 seconds 0.0.0.0:9200->9200/tcp, 9300/tcp elasticsearch
结果:
"tokens": [ "token": "我", "start_offset": 0, "end_offset": 1, "type": "CN_CHAR", "position": 0 , "token": "是", "start_offset": 1, "end_offset": 2, "type": "CN_CHAR", "position": 1 , "token": "中国人", "start_offset": 2, "end_offset": 5, "type": "CN_WORD", "position": 2 , "token": "中国", "start_offset": 2, "end_offset": 4, "type": "CN_WORD", "position": 3 , "token": "国人", "start_offset": 3, "end_offset": 5, "type": "CN_WORD", "position": 4 ]
可以看到,已经对中文进行了分词。
全文搜索
全文搜索两个最重要的方面是:
- 相关性(Relevance) 它是评价查询与其结果间的相关程度,并根据这种相关程度对结果排名的一种能力,这种计算方式可以是 TF/IDF 方法、地理位置邻近、模糊相似,或其他的某些算法。
- 分词(Analysis) 它是将文本块转换为有区别的、规范化的 token 的一个过程,目的是为了创建倒排索引以及查询倒排索引。
"acknowledged": true, "shards_acknowledged": true, "index": "topcheer"
批量插入数据
结果:
"took": 213, "errors": false, "items": [ "index": "_index": "topcheer", "_type": "person", "_id": "AXFzovfLg3Eko2bZmO_B", "_version": 1, "result": "created", "_shards": "total": 2, "successful": 1, "failed": 0 , "created": true, "status": 201 , "index": "_index": "itcast", "_type": "person", "_id": "AXFzovfLg3Eko2bZmO_C", "_version": 1, "result": "created", "_shards": "total": 2, "successful": 1, "failed": 0 , "created": true, "status": 201 , "index": "_index": "itcast", "_type": "person", "_id": "AXFzovfLg3Eko2bZmO_D", "_version": 1, "result": "created", "_shards": "total": 2, "successful": 1, "failed": 0 , "created": true, "status": 201 , "index": "_index": "itcast", "_type": "person", "_id": "AXFzovfLg3Eko2bZmO_E", "_version": 1, "result": "created", "_shards": "total": 2, "successful": 1, "failed": 0 , "created": true, "status": 201 ]
单词搜索
结果:
"took": 38, "timed_out": false, "_shards": "total": 5, "successful": 5, "skipped": 0, "failed": 0 , "hits": "total": 1, "max_score": 1.3123269, "hits": [ "_index": "itcast", "_type": "person", "_id": "AXFzovfLg3Eko2bZmO_D", "_score": 1.3123269, "_source": "name": "王五", "age": 22, "mail": "333@qq.com", "hobby": "羽毛球、篮球、游泳、听音乐" , "highlight": "hobby": [ "羽毛球、篮球、游泳、听<em>音</em><em>乐</em>" ] ]
过程说明:
1. 检查字段类型
爱好 hobby 字段是一个 text 类型( 指定了IK分词器),这意味着查询字符串本身也应该被分词。
2. 分析查询字符串 。
将查询的字符串 “音乐” 传入IK分词器中,输出的结果是单个项 音乐。因为只有一个单词项,所以 match 查询执行的是单个底层 term 查询。
3. 查找匹配文档 。
用 term 查询在倒排索引中查找 “音乐” 然后获取一组包含该项的文档
4. 为每个文档评分 。
用 term 查询计算每个文档相关度评分 _score ,这是种将 词频(term frequency,即词 “音乐” 在相关文档的hobby 字段中出现的频率)和 反向文档频率(inverse document frequency,即词 “音乐” 在所有文档的hobby 字段中出现的频率),以及字段的长度(即字段越短相关度越高)相结合的计算方式。
多词搜索
结果:
"took": 5, "timed_out": false, "_shards": "total": 1, "successful": 1, "skipped": 0, "failed": 0 , "hits": "total": 3, "max_score": 1.2632889, "hits": [ "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_K", "_score": 1.2632889, "_source": "name": "王五", "age": 22, "mail": "333@qq.com", "hobby": "羽毛球、篮球、游泳、听音乐" , "highlight": "hobby": [ "羽毛球、<em>篮球</em>、游泳、听<em>音乐</em>" ] , "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_L", "_score": 0.42327404, "_source": "name": "赵六", "age": 23, "mail": "444@qq.com", "hobby": "跑步、游泳、篮球" , "highlight": "hobby": [ "跑步、游泳、<em>篮球</em>" ] , "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_J", "_score": 0.2887157, "_source": "name": "李四", "age": 21, "mail": "222@qq.com", "hobby": "羽毛球、乒乓球、足球、篮球" , "highlight": "hobby": [ "羽毛球、乒乓球、足球、<em>篮球</em>" ] ]
可以看到,包含了“音乐”、“篮球”的数据都已经被搜索到了。
可是,搜索的结果并不符合我们的预期,因为我们想搜索的是既包含“音乐”又包含“篮球”的用户,显然结果返回的“或”的关系。
在Elasticsearch中,可以指定词之间的逻辑关系,如下:
结果:
"took": 7, "timed_out": false, "_shards": "total": 1, "successful": 1, "skipped": 0, "failed": 0 , "hits": "total": 1, "max_score": 1.2632889, "hits": [ "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_K", "_score": 1.2632889, "_source": "name": "王五", "age": 22, "mail": "333@qq.com", "hobby": "羽毛球、篮球、游泳、听音乐" , "highlight": "hobby": [ "羽毛球、<em>篮球</em>、游泳、听<em>音乐</em>" ] ]
可以看到结果符合预期。
前面我们测试了“OR” 和 “AND”搜索,这是两个极端,其实在实际场景中,并不会选取这2个极端,更有可能是选取这种,或者说,只需要符合一定的相似度就可以查询到数据,在Elasticsearch中也支持这样的查询,通过minimum_should_match来指定匹配度,如:70%;
示例:
结果:
"took": 3, "timed_out": false, "_shards": "total": 1, "successful": 1, "skipped": 0, "failed": 0 , "hits": "total": 3, "max_score": 1.2632889, "hits": [ "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_K", "_score": 1.2632889, "_source": "name": "王五", "age": 22, "mail": "333@qq.com", "hobby": "羽毛球、篮球、游泳、听音乐" , "highlight": "hobby": [ "羽毛球、<em>篮球</em>、游泳、听<em>音乐</em>" ] , "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_L", "_score": 0.42327404, "_source": "name": "赵六", "age": 23, "mail": "444@qq.com", "hobby": "跑步、游泳、篮球" , "highlight": "hobby": [ "跑步、游泳、<em>篮球</em>" ] , "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_J", "_score": 0.2887157, "_source": "name": "李四", "age": 21, "mail": "222@qq.com", "hobby": "羽毛球、乒乓球、足球、篮球" , "highlight": "hobby": [ "羽毛球、乒乓球、足球、<em>篮球</em>" ] ]
组合搜索
在搜索时,也可以使用过滤器中讲过的bool组合查询,示例:
上面搜索的意思是:
搜索结果中必须包含篮球,不能包含音乐,如果包含了游泳,那么它的相似度更高。
结果:
"took": 5, "timed_out": false, "_shards": "total": 1, "successful": 1, "skipped": 0, "failed": 0 , "hits": "total": 2, "max_score": 1.2458471, "hits": [ "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_L", "_score": 1.2458471, "_source": "name": "赵六", "age": 23, "mail": "444@qq.com", "hobby": "跑步、游泳、篮球" , "highlight": "hobby": [ "跑步、<em>游泳</em>、<em>篮球</em>" ] , "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_J", "_score": 0.2887157, "_source": "name": "李四", "age": 21, "mail": "222@qq.com", "hobby": "羽毛球、乒乓球、足球、篮球" , "highlight": "hobby": [ "羽毛球、乒乓球、足球、<em>篮球</em>" ] ]
评分的计算规则
bool 查询会为每个文档计算相关度评分 _score , 再将所有匹配的 must 和 should 语句的分数 _score 求和,最后除以 must 和 should 语句的总数。
must_not 语句不会影响评分; 它的作用只是将不相关的文档排除。默认情况下,should中的内容不是必须匹配的,如果查询语句中没有must,那么就会至少匹配其中一个。当然了,也可以通过minimum_should_match参数进行控制,该值可以是数字也可以的百分比。
示例:
结果:
"took": 3, "timed_out": false, "_shards": "total": 1, "successful": 1, "skipped": 0, "failed": 0 , "hits": "total": 2, "max_score": 1.8243669, "hits": [ "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_K", "_score": 1.8243669, "_source": "name": "王五", "age": 22, "mail": "333@qq.com", "hobby": "羽毛球、篮球、游泳、听音乐" , "highlight": "hobby": [ "羽毛球、<em>篮球</em>、<em>游泳</em>、听<em>音乐</em>" ] , "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_L", "_score": 1.2458471, "_source": "name": "赵六", "age": 23, "mail": "444@qq.com", "hobby": "跑步、游泳、篮球" , "highlight": "hobby": [ "跑步、<em>游泳</em>、<em>篮球</em>" ] ]
权重
有些时候,我们可能需要对某些词增加权重来影响该条数据的得分。如下:
搜索关键字为“游泳篮球”,如果结果中包含了“音乐”权重为10,包含了“跑步”权重为2。
结果:
"took": 5, "timed_out": false, "_shards": "total": 1, "successful": 1, "skipped": 0, "failed": 0 , "hits": "total": 2, "max_score": 10.595525, "hits": [ "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_K", "_score": 10.595525, "_source": "name": "王五", "age": 22, "mail": "333@qq.com", "hobby": "羽毛球、篮球、游泳、听音乐" , "highlight": "hobby": [ "羽毛球、<em>篮球</em>、<em>游泳</em>、听<em>音乐</em>" ] , "_index": "topcheer", "_type": "person", "_id": "AXFzrtEJg3Eko2bZmO_L", "_score": 4.1034093, "_source": "name": "赵六", "age": 23, "mail": "444@qq.com", "hobby": "跑步、游泳、篮球" , "highlight": "hobby": [ "<em>跑步</em>、<em>游泳</em>、<em>篮球</em>" ] ]
elasticsearch自定义分词器(代码片段)
...检索,就必须对文档按照拼音分词。在GitHub上恰好有elasticsearch的拼音分词插件。地址:https://github.com/medcl/elasticsearch-analysis-pinyin 把yinpin分词器拷贝到es的/plugins目录里面 重启es的容器:dock 查看详情
elasticsearch拼音分词和ik分词的安装及使用(代码片段)
...八九使用的都是IK分词器。下载地址:https://github.com/medcl/elasticsearch-analysis-ik2.pinyin分词器的下载安装可以在淘宝、京东的搜索框中输入pinyin就能查找到自己想要的结 查看详情
elasticsearch实现分词全文检索(代码片段)
...completion,然后之后的suggest针对title.suggest字段做操作目录ElasticSearch实现分词全文检索-概述ElasticSearch实现分词全文检索-ES、Kibana、IK安装ElasticSearch实现分词全文检索-Restful基本操作ElasticSearch实现分词全文检索-JavaSpringBootES索引操... 查看详情
elasticsearch实现分词全文检索(代码片段)
搜素关键字自动补全(suggest),分词全文搜索系统初始化,ElasticSearchES创建索引(EsIndexTest.createIndexTest)模拟后台管理员,在添加文章时,将要检查的字段内容,同步到ES中(EsIndexTest.addArticleTest)模拟用户搜索,在搜索框中查关... 查看详情
elasticsearch-ik分词器(代码片段)
ElasticSearch-ik分词器IK分词器安装使用下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases下载对应版本即可:安装:下载箭头中的压缩包就行了,下载之后解压到elasticsearch的plugins的一个文件夹ik(ik文件夹自己创建,可以随意... 查看详情
elasticsearch安装中文分词器(代码片段)
发车 为什么要在elasticsearch中要使用ik这样的中文分词呢,那是因为es提供的分词是英文分词,对于中文的分词就做的非常不好了,因此我们需要一个中文分词器来用于搜索和使用。今天我们就尝试安装下IK分词。上... 查看详情
elasticsearch(十八)初识分词器(代码片段)
1、什么是分词器作用:切分词语,normalization(提升recall召回率),如给你一段句子,然后将这段句子拆分成一个一个的单个的单词,同时对每个单词进行normalization(时态转换,单复数转换),分词器recall,召回率:搜索的时候... 查看详情
elasticsearch安装elasticsearch-analysis-ik中文分词器(代码片段)
1,讲分词器的文件夹放入es安装包的plugins,重新启动elasticsearch//查询es运行中的进程pidps-aux|grepelasticsearch//杀死进程kill-9pid//使用es账户启动nohup./elasticsearch&2,重启es,然后在新建index的type表结构时,需要指定将来可能要使用... 查看详情
elasticsearch安装elasticsearch-analysis-ik中文分词器(代码片段)
1,讲分词器的文件夹放入es安装包的plugins,重新启动elasticsearch//查询es运行中的进程pidps-aux|grepelasticsearch//杀死进程kill-9pid//使用es账户启动nohup./elasticsearch&2,重启es,然后在新建index的type表结构时,需要指定将来可能要使用... 查看详情
elasticsearch实践:ik分词(代码片段)
环境:Elasticsearch6.2.4+Kibana6.2.4+ik6.2.4Elasticsearch默认也能对中文进行分词。我们先来看看自带的中文分词效果:curl-XGET"http://localhost:9200/_analyze"-H'Content-Type:application/json'-d'"analyzer&quo 查看详情
elasticsearch实战(二十六)-ik中文分词器(代码片段)
为什么要在elasticsearch中要使用ik这样的中文分词?因为ES提供的分词是英文分词,对于中文的分词就做的非常不好了,因此我们需要一个中文分词器来用于搜索和使用。一、安装 我们可以从 官... 查看详情
elasticsearch分词器的使用与ik分词器安装(代码片段)
Elasticsearch分词器安装与使用ES内置分词器standard:默认分词器,简单会被拆分,英文统一转换为小写simlle:按照非字母分词,英文统一转换为小写whitespace:按照空格分词stop:去除无意义的单词,比... 查看详情
elasticsearch:计数分词中的token(代码片段)
...对分词器还不是很理解的话,请参考我之前的文章“Elasticsearch:analyzer”。在分词时,有一个叫做token_count的类型。该类型是token的计数器,也就是说,我们可以使用它来了解在索引字段时在字符串中生成的token数 查看详情
elasticsearch-ik分词器;文档得分机制(代码片段)
阅读本文前可先参考Elasticsearch-Kibana(四)_MinggeQingchun的博客-CSDN博客https://blog.csdn.net/MinggeQingchun/article/details/126768243一、IK分词器中文分词ES的默认分词器无法识别中文中测试、单词这样的词汇,而是简单的将每个字... 查看详情
elasticsearch:从零开始构建一个定制的分词器(代码片段)
Elasticsearch提供了大量的analyzer和tokenizer来满足开箱即用的一般需求。有时,我们需要通过添加新的分析器来扩展Elasticsearch的功能。尽管Elastic提供了丰富的分词器,但是在很多的时候,我们希望为自己的语言或一种特... 查看详情
elasticsearch:分词器中的token过滤器使用示例(代码片段)
分词器在Elasticsearch的使用中非常重要。分词器中的过滤器可以帮我们对最终的分词进行处理,从而使得我们得到的最终分词会影响存储的大小和搜索的方式。在今天的文章中,我来分享一下一些常用的分词器中的token过... 查看详情
elasticsearch中文分词(代码片段)
...hobby","text":"听音乐" 中文分词: IK分词器Elasticsearch插件地址:https://github.com/medcl/elasticsearch-analysis-ik 安装方法:将下载到的elasticsearch-analysis-ik-6.5.4.zip解压到elasticsearch/plugins/ik目录下即可。 unzipelastics... 查看详情
docker安装elasticsearch的中文分词器ik(代码片段)
主要问题一定要保证ElasticSearch和ElasticSearch插件的版本一致我是用的是ElasticSearch是5.6.11版本对应elasticsearch-analysis-ik-5.6.11安装插件在线安装进入容器dockerexec-itelasticsearch/bin/bash在线下载并安装./bin/elasticsearch-plugininstallhttps://github.co... 查看详情