elasticsearch的分词(代码片段)

dalianpai dalianpai     2023-04-03     734

关键词:

什么是分词

分词就是指将一个文本转化成一系列单词的过程,也叫文本分析,在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
        
    ]

可以看到,已经对中文进行了分词。

全文搜索
全文搜索两个最重要的方面是:

  1. 相关性(Relevance) 它是评价查询与其结果间的相关程度,并根据这种相关程度对结果排名的一种能力,这种计算方式可以是 TF/IDF 方法、地理位置邻近、模糊相似,或其他的某些算法。
  2. 分词(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... 查看详情