初次接触 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. 微服务架构基础之Service Mesh

    ServiceMesh(服务网格) 概念在社区里头非常火,有人提出 2018 年是 ServiceMesh 年,还有人提出 ServiceMesh 是下一代的微服务架构基础. 那么到底什么是 Serv ...

  2. 大量Python开源第三方库资源分类整理,含菜鸟教程章节级别链接

    Python是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明.因其具有丰富和强大的库,它常被称为胶水语言,能够把用其它语言制作的各种模块(尤其是C/C ...

  3. jQuery validdate插件的使用

    跟着书上的例子做的时候发现很奇怪,在script标签中用message重写提示消息,没有反应,不知道是不是引入的metadata.js文件有问题,于是用了菜鸟教程的cdn和教程,魔改了一下 <! ...

  4. python基础1.0

    1. python简介:解释性语言 安装python,注意路径加入path python的解释器,cpython,Python的解释器很多,但使用最广泛的还是CPython.如果要和Java或.Net ...

  5. python3 字典update与deepcopy

    问题概述: 在码代码中,需要保存一个字典,用的update,后来发现update的值会随着原字典值得变化而变化. 而后使用deepcopy来保存字典. update a = {1:{2:3}}b= { ...

  6. Tinker热修复

    集成buggly热修复的时候报错 Error:A problem occurred configuring project ‘:app’. Failed to notify project evalu ...

  7. R数据导入导出(一): read.table()和read.csv()的区别

    之前也参考过一些资料,虽然是这么简单的两个buildin,还是仔细对比了一下,我有两张txt,都是从cube中导出的,就意味着每一列的列数是不一样的.R语言官方文档中有这样一句话不知道大家注意到了没有 ...

  8. fiddler抓https包

    若手机端安装证书后还是无法抓取到https请求,请注意手机端证书开关是否开启: eg:ios 设置---通用---关于本机---证书信任设置:开启证书信任 若还是无法抓包,则可以进行一下操作: 给fi ...

  9. 关于ASP.NET 服务器报错 Server Error in '/' Application Runtime Error 错误及解决方法

    今天遇到一个错误 程序在服务器上运行时报错 先贴上错误代码 自己也在网上找了一些解决方法,把错误定位到服务器的配置文件也就是Web.config的问题, 于是在system.web节点下 加上cust ...

  10. nginx 做数据仓库时,location 404 Not Found,发现找不到要用的数据报:Not Found

    背景:  获得远程机器某个目录下的数据文件 方案:使用Nginx配置 1./home/ftp/www/ 下面有images 文件夹,为了访问images下面文件,配置Nginx如下: location ...