初次接触 Elasticsearch 的同学经常会遇到分词相关的难题,比如如下这些场景:

1.为什么明明有包含搜索关键词的文档,但结果里面就没有相关文档呢?

2.我存进去的文档到底被分成哪些词(term)了?

3.我自定义分词规则,但感觉好麻烦呢,无从下手

1.从一个实例出发,如下创建一个文档:

然后我们做一个查询,我们试图通过搜索 eat 这个关键词来搜索这个文档

ES的返回结果为0。这不太对啊,我们用最基本的字符串查找也应该能匹配到上面新建的文档才对啊!

先来看看什么是分词。

2. 分词

搜索引擎的核心是倒排索引,而倒排索引的基础就是分词。所谓分词可以简单理解为将一个完整的句子切割为一个个单词的过程。在 es 中单词对应英文为 term 。我们简单看个例子:

ES 的倒排索引即是根据分词后的单词创建,即我、爱、北京、天安门这4个单词。这也意味着你在搜索的时候也只能搜索这4个单词才能命中该文档。

实际上 ES 的分词不仅仅发生在文档创建的时候,也发生在搜索的时候,如下图所示:

读时分词发生在用户查询时,ES 会即时地对用户输入的关键词进行分词,分词结果只存在内存中,当查询结束时,分词结果也会随即消失。而写时分词发生在文档写入时,ES 会对文档进行分词后,将结果存入倒排索引,该部分最终会以文件的形式存储于磁盘上,不会因查询结束或者 ES 重启而丢失。

ES 中处理分词的部分被称作分词器,英文是Analyzer,它决定了分词的规则。ES 自带了很多默认的分词器,比如Standard、Keyword、Whitespace等等,默认是Standard。当我们在读时或者写时分词时可以指定要使用的分词器。

3. 写时分词结果

回到上手阶段,我们来看下写入的文档最终分词结果是什么。通过如下 api 可以查看:

其中test为索引名,_analyze为查看分词结果的endpoint,请求体中field为要查看的字段名,text为具体值。该 api 的作用就是请告诉我在 test 索引使用 msg 字段存储一段文本时,es 会如何分词。

返回结果如下:

返回结果中的每一个token即为分词后的每一个单词,我们可以看到这里是没有eat这个单词的,这也解释了在上手中我们搜索eat没有结果的情况。如果你去搜索eating,会有结果返回。

写时分词器需要在 mapping 中指定,而且一经指定就不能再修改,若要修改必须新建索引。如下所示我们新建一个名为ms_english的字段,指定其分词器为english:

4. 读时分词结果

由于读时分词器默认与写时分词器默认保持一致,拿 上手 中的例子,你搜索msg字段,那么读时分词器为Standard,搜索msg_english时分词器则为english。这种默认设定也是非常容易理解的,读写采用一致的分词器,才能尽最大可能保证分词的结果是可以匹配的。

然后 ES 允许读时分词器单独设置,如下所示:

如上analyzer字段即可以自定义读时分词器,一般来讲不需要特别指定读时分词器。

如果不单独设置分词器,那么读时分词器的验证方法与写时一致;如果是自定义分词器,那么可以使用如下的 api 来自行验证结果。

返回结果如下:

由上可知english分词器会将eating处理为eat,大家可以再测试下默认的standard分词器,它没有做任何处理。

5. 解释问题

现在我们再来看下 上手 中所遇问题的解决思路。

查看文档写时分词结果查看查询关键词的读时分词结果匹对两者是否有命中

我们简单分析如下:

由上图可以定位问题的原因了。

6. 解决需求

由于eating只是eat的一个变形,我们依然希望输入eat时可以匹配包含eating的文档,那么该如何解决呢?答案很简单,既然原因是在分词结果不匹配,那么我们就换一个分词器呗~ 我们可以先试下 ES 自带的english

分词器,如下:

执行上面的内容,我们会发现结果有内容了,原因也很简单,如下图所示:

由上图可见english分词器会将eating分词为eat,此时我们搜索eat或者eating肯定都可以匹配对应的文档了。至此,需求解决。

7. 深入分析

最后我们来看下为什么english分词器可以解决我们遇到的问题。一个分词器由三部分组成:char filter、tokenizer 和 token filter。各部分的作用我们这里就不展开了,我们来看下standard和english分词器的区别。

从上图可以看出,english分词器在 Token Filter 中和Standard不同,而发挥主要作用的就是stemmer,感兴趣的同学可以自行去看其它的作用。

8. 自定义分词

如果我们不使用english分词器,自定义一个分词器来实现上述需求也是完全可行的,这里不详细讲解了,只给大家讲一个快速验证自定义分词器效果的方法,如下:

通过上面的 api 你可以快速验证自己要定制的分词器,当达到自己需求后,再将这一部分配置加入索引的配置。

至此,我们再看开篇的三个问题,相信你已经心里有答案了

[ES]elasticsearch章5 ES的分词(一)的更多相关文章

  1. [ES]elasticsearch章5 ES的分词(二)

    Elasticsearch 中文搜索时遇到几个问题: 当搜索关键词如:“人民币”时,如果分词将“人民币”分成“人”,“民”,“币”三个单字,那么搜索该关键词会匹配到很多包含该单字的无关内容,但是如果将 ...

  2. [ES]elasticsearch章4 ES的META们

    在介绍Meta更新流程前,我们先介绍一下ES中Meta的组成.存储方式和恢复方式. 1. Meta:ClusterState.MetaData.IndexMetaData Meta是用来描述数据的数据 ...

  3. [ES]elasticsearch章3 ES写入过程解析

    Elasticsearch的写 Elasticsearch采用多Shard方式,通过配置routing规则将数据分成多个数据子集,每个数据子集提供独立的索引和搜索功能.当写入文档的时候,根据routi ...

  4. [ES]elasticsearch章2 ES查询过程解析

    es服务端是准确知道每个document分布在哪个shard上: search一个比较复杂的执行模式,因为我们不知道那些document会被匹配到,任何一个shard上都有可能,所以一个search请 ...

  5. [ES]elasticsearch章1 ES各角色的分工

    es集群里的master node.data node和client node到底是怎么个意思,分别有何特点? master节点 主要功能是维护元数据,管理集群各个节点的状态,数据的导入和查询都不会走 ...

  6. Elasticsearch使用系列-ES增删查改基本操作+ik分词

    Elasticsearch使用系列-ES简介和环境搭建 Elasticsearch使用系列-ES增删查改基本操作+ik分词 一.安装可视化工具Kibana ES是一个NoSql数据库应用.和其他数据库 ...

  7. Elasticsearch前沿:ES 5.x改进详解与ES6展望

    转:http://www.dataguru.cn/article-11094-1.html 曾勇(Medcl),Elastic 工程师与布道师,2015 年加入 Elastic 公司.加入 Elast ...

  8. centos7使用docker安装es(elasticsearch)

    1.安装docker依赖(已安装可以不用安装) yum install -y docker 2.搜索镜像 docker search elasticsearch 如果出现以下报错 Cannot con ...

  9. ElasticSearch(简称ES)

    Windows下安装ElasticSearch   ElasticSearch(简称ES)是一个基于Lucene的分布式全文搜索服务器,和SQL Server的全文索引(Fulltext Index) ...

随机推荐

  1. 【python】django上传文件

    参考:https://blog.csdn.net/zahuopuboss/article/details/54891917 参考:https://blog.csdn.net/zzg_550413470 ...

  2. 关于XML的小思考

    最近一段时间又接触了XML语言,现在看来它是一种可扩展标记语言,它的格式是标签语言,例如<>****<>此类,它在动态编译中有重要的作用,举个例子,一个班级里有37个人,到学期 ...

  3. Linux网络编程学习(十二) ----- 结语

    该书提前看完了,重点看了第四章和第六章,第七章以后只是大致浏览了一下,如果以后工作中涉及这一块再仔细研究一下,大概花了二十天的样子,主要了解了进程间的通信方式.socket编程以及五种I/O模式,看的 ...

  4. [Go] 开始试探一门新语言的五点思考 - Golang

    1.如果在其他语言环境中写的代码很烂,那么换一门语言很可能情况更糟,因为是涉及到基本功.工程能力和心思逻辑. 2.一定要了解语言解决的问题(比如:多核并发机制性能高.省机器.简洁易学.资料少),优势是 ...

  5. Rsync + Lsyncd服务实现文件实时同步/备份

    1.接受端安装rsync yum -y install rsync 2.配置同步模块 vim /etc/rsyncd.conf # any name you like [backup] # desti ...

  6. Servlet中清除session

    HttpSession sessions = request.getSession(false);//防止创建Session if(sessions == null){ response.sendRe ...

  7. 20175213 2018-2019-2 《Java程序设计》第4周学习总结

    ## 教材学习内容总结 在第四周的学习过程中,我学习了第五章的内容. 第五章内容总结: 1.子类继承的方法只能操作子类继承和隐藏的成员变量. 2.子类和父类在同一包的继承性 子类自然继承了其父类中不是 ...

  8. SpringCloud-day09-Feign与Hystrix整合

    8.5.Feign 与 Hystrix整合 服务熔断服务降级彻底解耦 前面的代码,用@HystrixCommand fallbackMethod是很不好的,因为和业务代码耦合度太高,不利于维护,所以需 ...

  9. linux下安装zabbix

    1.安装源:sudo rpm -ivh http://repo.zabbix.com/zabbix/3.2/rhel/6/i386/zabbix-release-3.2-1.el6.noarch.rp ...

  10. Git安装配置,和使用的简介

    方案1:安装Git和TortoiseGit,使用TortoiseGit的图形化界面管理项目代码 材料准备: Git安装包 TortoiseGit安装包 注:包资源,可疑百度搜索,在Git官网下载 安装 ...