社区日报 第375期 (2018-08-26)
社区日报 • 至尊宝 发表了文章 • 0 个评论 • 2227 次浏览 • 2018-08-26 08:22
http://t.cn/Rk1SYUC
2.(自备梯子)四大NoSQL数据库。
http://t.cn/Rk1anR2
3.(自备梯子)您必须在“按时交付的软件”和“良好软件”之间进行选择。
http://t.cn/Rk1abPX
活动预告:
1、Elastic 中国开发者大会最后一波早鸟票发售进行中
https://conf.elasticsearch.cn/2018/shenzhen.html
2、Elastic Meetup 9月8日 北京线下沙龙正在报名中
https://elasticsearch.cn/article/759
编辑:至尊宝
归档:https://elasticsearch.cn/article/772
订阅:https://tinyletter.com/elastic-daily
掌握 analyze API,一举搞定 Elasticsearch 分词难题
Elasticsearch • rockybean 发表了文章 • 1 个评论 • 27047 次浏览 • 2018-08-25 22:44
初次接触 Elasticsearch 的同学经常会遇到分词相关的难题,比如如下这些场景:
- 为什么明明有包含搜索关键词的文档,但结果里面就没有相关文档呢?
- 我存进去的文档到底被分成哪些词(term)了?
- 我得自定义分词规则,但感觉好麻烦呢,无从下手
如果你遇到过类似的问题,希望本文可以解决你的疑惑。
1. 上手
让我们从一个实例出发,如下创建一个文档:
json<br /> PUT test/doc/1<br /> {<br /> "msg":"Eating an apple a day keeps doctor away"<br /> }<br />
然后我们做一个查询,我们试图通过搜索eat
这个关键词来搜索这个文档
json<br /> POST test/_search<br /> {<br /> "query":{<br /> "match":{<br /> "msg":"eat"<br /> }<br /> }<br /> }<br />
ES的返回结果为0。这不太对啊,我们用最基本的字符串查找也应该能匹配到上面新建的文档才对啊!
各位不要急,我们先来看看什么是分词。
2. 分词
搜索引擎的核心是倒排索引(这里不展开讲),而倒排索引的基础就是分词。所谓分词可以简单理解为将一个完整的句子切割为一个个单词的过程。在 es 中单词对应英文为term
。我们简单看个例子:

ES 的倒排索引即是根据分词后的单词创建,即我
、爱
、北京
、天安门
这4个单词。这也意味着你在搜索的时候也只能搜索这4个单词才能命中该文档。
实际上 ES 的分词不仅仅发生在文档创建的时候,也发生在搜索的时候,如下图所示:

读时分词
发生在用户查询时,ES 会即时地对用户输入的关键词进行分词,分词结果只存在内存中,当查询结束时,分词结果也会随即消失。而写时分词
发生在文档写入时,ES 会对文档进行分词后,将结果存入倒排索引,该部分最终会以文件的形式存储于磁盘上,不会因查询结束或者 ES 重启而丢失。
ES 中处理分词的部分被称作分词器,英文是Analyzer
,它决定了分词的规则。ES 自带了很多默认的分词器,比如Standard
、Keyword
、Whitespace
等等,默认是Standard
。当我们在读时或者写时分词时可以指定要使用的分词器。
3. 写时分词结果
回到上手阶段,我们来看下写入的文档最终分词结果是什么。通过如下 api 可以查看:
json<br /> POST test/_analyze<br /> {<br /> "field": "msg",<br /> "text": "Eating an apple a day keeps doctor away"<br /> }<br />
其中test
为索引名,_analyze
为查看分词结果的endpoint
,请求体中field
为要查看的字段名,text
为具体值。该 api 的作用就是请告诉我在 test 索引使用 msg 字段存储一段文本时,es 会如何分词。
返回结果如下:
json<br /> {<br /> "tokens": [<br /> {<br /> "token": "eating",<br /> "start_offset": 0,<br /> "end_offset": 6,<br /> "type": "<ALPHANUM>",<br /> "position": 0<br /> },<br /> {<br /> "token": "an",<br /> "start_offset": 7,<br /> "end_offset": 9,<br /> "type": "<ALPHANUM>",<br /> "position": 1<br /> },<br /> {<br /> "token": "apple",<br /> "start_offset": 10,<br /> "end_offset": 15,<br /> "type": "<ALPHANUM>",<br /> "position": 2<br /> },<br /> {<br /> "token": "a",<br /> "start_offset": 16,<br /> "end_offset": 17,<br /> "type": "<ALPHANUM>",<br /> "position": 3<br /> },<br /> {<br /> "token": "day",<br /> "start_offset": 18,<br /> "end_offset": 21,<br /> "type": "<ALPHANUM>",<br /> "position": 4<br /> },<br /> {<br /> "token": "keeps",<br /> "start_offset": 22,<br /> "end_offset": 27,<br /> "type": "<ALPHANUM>",<br /> "position": 5<br /> },<br /> {<br /> "token": "doctor",<br /> "start_offset": 28,<br /> "end_offset": 34,<br /> "type": "<ALPHANUM>",<br /> "position": 6<br /> },<br /> {<br /> "token": "away",<br /> "start_offset": 35,<br /> "end_offset": 39,<br /> "type": "<ALPHANUM>",<br /> "position": 7<br /> }<br /> ]<br /> }<br />
返回结果中的每一个token
即为分词后的每一个单词,我们可以看到这里是没有eat
这个单词的,这也解释了在上手中我们搜索eat
没有结果的情况。如果你去搜索eating
,会有结果返回。
写时分词器需要在 mapping 中指定,而且一经指定就不能再修改,若要修改必须新建索引。如下所示我们新建一个名为ms_english
的字段,指定其分词器为english
:
json<br /> PUT test/_mapping/doc<br /> {<br /> "properties": {<br /> "msg_english":{<br /> "type":"text",<br /> "analyzer": "english"<br /> }<br /> }<br /> }<br />
4. 读时分词结果
由于读时分词器默认与写时分词器默认保持一致,拿 上手 中的例子,你搜索msg
字段,那么读时分词器为Standard
,搜索msg_english
时分词器则为english
。这种默认设定也是非常容易理解的,读写采用一致的分词器,才能尽最大可能保证分词的结果是可以匹配的。
然后 ES 允许读时分词器单独设置,如下所示:
json<br /> POST test/_search<br /> {<br /> "query":{<br /> "match":{<br /> "msg":{<br /> "query": "eating",<br /> "analyzer": "english"<br /> }<br /> }<br /> }<br /> }<br />
如上analyzer
字段即可以自定义读时分词器,一般来讲不需要特别指定读时分词器。
如果不单独设置分词器,那么读时分词器的验证方法与写时一致;如果是自定义分词器,那么可以使用如下的 api 来自行验证结果。
json<br /> POST _analyze<br /> {<br /> "text":"eating",<br /> "analyzer":"english"<br /> }<br />
返回结果如下:
json<br /> {<br /> "tokens": [<br /> {<br /> "token": "eat",<br /> "start_offset": 0,<br /> "end_offset": 6,<br /> "type": "<ALPHANUM>",<br /> "position": 0<br /> }<br /> ]<br /> }<br />
由上可知english
分词器会将eating
处理为eat
,大家可以再测试下默认的standard
分词器,它没有做任何处理。
5. 解释问题
现在我们再来看下 上手 中所遇问题的解决思路。
- 查看文档写时分词结果
- 查看查询关键词的读时分词结果
- 匹对两者是否有命中
我们简单分析如下:

由上图可以定位问题的原因了。
6. 解决需求
由于eating
只是eat
的一个变形,我们依然希望输入eat
时可以匹配包含eating
的文档,那么该如何解决呢?
答案很简单,既然原因是在分词结果不匹配,那么我们就换一个分词器呗~ 我们可以先试下 ES 自带的english
分词器,如下:
```json增加字段 msg_english,与 msg 做对比
PUT test/_mapping/doc
{
"properties": {
"msg_english":{
"type":"text",
"analyzer": "english"
}
}
}
写入相同文档
PUT test/doc/1
{
"msg":"Eating an apple a day keeps doctor away",
"msg_english":"Eating an apple a day keeps doctor away"
}
搜索 msg_english 字段
POST test/_search
{
"query": {
"match": {
"msg_english": "eat"
}
}
}
``<br /> <br /> <br /> <br /> 执行上面的内容,我们会发现结果有内容了,原因也很简单,如下图所示:<br /> <br /> <br /> <br /> 由上图可见
english分词器会将
eating分词为
eat,此时我们搜索
eat或者
eating`肯定都可以匹配对应的文档了。至此,需求解决。
7. 深入分析
最后我们来看下为什么english
分词器可以解决我们遇到的问题。一个分词器由三部分组成:char filter、tokenizer 和 token filter。各部分的作用我们这里就不展开了,我们来看下standard
和english
分词器的区别。

从上图可以看出,english
分词器在 Token Filter 中和Standard
不同,而发挥主要作用的就是stemmer
,感兴趣的同学可以自行去看起它的作用。
8. 自定义分词
如果我们不使用english
分词器,自定义一个分词器来实现上述需求也是完全可行的,这里不详细讲解了,只给大家讲一个快速验证自定义分词器效果的方法,如下:
json<br /> POST _analyze<br /> {<br /> "char_filter": [], <br /> "tokenizer": "standard",<br /> "filter": [<br /> "stop",<br /> "lowercase",<br /> "stemmer"<br /> ],<br /> "text": "Eating an apple a day keeps doctor away"<br /> }<br />
通过上面的 api 你可以快速验证自己要定制的分词器,当达到自己需求后,再将这一部分配置加入索引的配置。
至此,我们再看开篇的三个问题,相信你已经心里有答案了,赶紧上手去自行测试下吧!

社区日报 第374期 (2018-08-25)
社区日报 • bsll 发表了文章 • 0 个评论 • 1932 次浏览 • 2018-08-25 12:34
- ES6.4发布。
[http://t.cn/RkHPfV6](http://t.cn/RkHPfV6)
- 在Django项目中使用es。
[http://t.cn/RkR2as4](http://t.cn/RkR2as4)
- ElasticHQ: 基于python的es监控管理插件。
[http://t.cn/Rk8ioV0](http://t.cn/Rk8ioV0)
活动预告
1、Elastic 中国开发者大会最后一波早鸟票发售进行中
https://conf.elasticsearch.cn/2018/shenzhen.html
2、Elastic Meetup 9月8日 北京线下沙龙正在报名中
https://elasticsearch.cn/article/759
elasticsearch 均衡策略分片选择疑问
Elasticsearch • rochy 回复了问题 • 4 人关注 • 1 个回复 • 4995 次浏览 • 2018-08-27 09:19
关闭index可能会消耗大量的磁盘空间
Elasticsearch • luman 回复了问题 • 2 人关注 • 1 个回复 • 2323 次浏览 • 2018-08-24 18:18
logstash 已启动采集logback的日志,我再配置一个文件,利用filebeat采集nginx的日志,可以启动两个logstash实例吗?
Logstash • zyy 回复了问题 • 2 人关注 • 1 个回复 • 3358 次浏览 • 2018-08-27 10:02
ES 6.3+ Query Cache失效?
Elasticsearch • lingerchouzi 回复了问题 • 17 人关注 • 10 个回复 • 6570 次浏览 • 2019-12-30 16:12
logstash 截取kafka 中的json中为空值的 不要这一个字段能做到么?
回复Logstash • zhangshuai 发起了问题 • 1 人关注 • 0 个回复 • 4837 次浏览 • 2018-08-24 14:39
Elastic Tips 项目
活动 • medcl 发表了文章 • 8 个评论 • 2926 次浏览 • 2018-08-24 11:55
场景:
大家是不是觉得 Elastic 的知识很多,需要学习的很多,常见问题经常问。
目的:
- 汇集 Elastic Stack 的奇巧赢技
- 随手可得的小技巧,温故知新
- 分享和学习,共同进步
- 积少成多,知识库
细节
- 贴士的内容要小且精要,简单,适合阅读和分享(限制为Twitter长度)
- 大家都可以发表贴士,社区一起参与贡献内容
- 贴士需要标识适用的版本号和对应的开源项目,如:Elasticsearch 6.x
- 贴士在得到3个赞之后,表示受到大家的认可,可以提供出现分享功能
- 分享功能要支持外部引用,生成 JS 脚本,随机显示一条贴士,可以挂在个人博客和网站上
- 可以对单条贴士生成一个图片,嵌入二维码,方便微信微博分享,显示贡献者和贡献者的个人签名
- 贴士不单独存储,还是在社区的文章模块,只不过发布的时候,需要选择分类为 “ElasticTips” 目录
- 搞一个微信小程序,方便分享传播贴士内容
开发内容:
- API 模块:Golang 编写,负责读取数据库内容和生成 JS,RSS 订阅
- JS 渲染模块:Golang 编写,负责渲染生成 JS
- 静态图片生成:Golang 编写,基于图片模板,渲染分享用的图片
- 单独的页面来展示贴士,主要要求是要酷炫
- 微信小程序:貌似没得选,再者我也不懂
好了,听起来有点意思,是不是很兴奋,那么问题来了,有没有兴趣一起来弄的呢?
有兴趣的请加入 Slack 讨论组。
float类型存储在es中会有精度损失
Elasticsearch • wjx1015 回复了问题 • 5 人关注 • 3 个回复 • 15069 次浏览 • 2018-09-25 15:04
集群健康值: 未连接
Elasticsearch • lucky_girl 回复了问题 • 2 人关注 • 2 个回复 • 6629 次浏览 • 2018-08-27 17:27
logstash-input-syslog接收多台设备日志的编码问题
Logstash • tyb1222 回复了问题 • 3 人关注 • 2 个回复 • 4160 次浏览 • 2018-08-24 12:01
社区日报 第373期 (2018-08-24)
社区日报 • laoyang360 发表了文章 • 0 个评论 • 1956 次浏览 • 2018-08-24 06:11
http://t.cn/RklH6TU
2、搜索之路:Elasticsearch的诞生
http://t.cn/Rk6ZPYq
3、教你编译调试Elasticsearch 6.3.2源码
http://t.cn/RklHW8y
活动预告:
1、Elastic Meetup 北京线下沙龙征稿中
https://elasticsearch.cn/article/759
2、Elastic 中国开发者大会 2018 ,开始接受演讲申请和赞助合作
https://conf.elasticsearch.cn/2018/shenzhen.html
编辑:铭毅天下
归档:https://elasticsearch.cn/article/768
订阅:https://tinyletter.com/elastic-daily
社区日报 第372期 (2018-08-23)
社区日报 • elk123 发表了文章 • 0 个评论 • 2316 次浏览 • 2018-08-23 20:38
http://t.cn/RkK4iEb
2.你真的理解grok吗?
http://t.cn/RkK4NwF
3.如何在Elasticsearch中使用排名评估API
http://t.cn/RkK4nQx
活动预告:
1、Elastic Meetup 北京线下沙龙征稿中
https://elasticsearch.cn/article/759
2、Elastic 中国开发者大会预热票发售进行中
https://conf.elasticsearch.cn/2018/shenzhen.html
编辑:金桥
归档:https://elasticsearch.cn/article/767
订阅:https://tinyletter.com/elastic-daily
linux 下 elasticsearch 自动启动 谁帮我指导一下,我的没启动成功
Elasticsearch • zqc0512 回复了问题 • 3 人关注 • 2 个回复 • 3165 次浏览 • 2018-08-24 09:54