官方原文连接:https://www.elastic.co/cn/blog/strings-are-dead-long-live-stringssegmentfault
转载原文链接:https://segmentfault.com/a/1190000008897731app
Text vs. keyword
随着ElasticSearch 5.0的到来, 同时也迎来了该版本的重大特性之一: 移除了string
类型. 这个变更的根本缘由是string
类型会给咱们带来不少困惑: 由于ElasticSearch对字符串拥有两种彻底不一样的搜索方式. 你能够按照整个文本进行匹配, 即关键词搜索(keyword search), 也能够按单个字符匹配, 即全文搜索(full-text search). 对ElasticSearch稍有了解的人都知道, 前者的字符串被称为not-analyzed
字符, 然后者被称做analyzed
字符串.flex
事实上, 同一种类型用于应对两种不一样的使用场景是会让人崩溃的, 由于有些选项只对其一的场景设置有效.例如position_increment_gap
对not-analyzed
字符就不会起做用, 而像ignore_above
对于analyzed
字符串就很难区分它究竟是对整个字符串的值有效仍是对单独的每一个分词有效(在这种场景, ignore_above确实只对整个字符串值有效, 而对单个分词的限制可使用limit
设置).url
为了不上述尴尬, string
字段被拆分红两种新的数据类型: text
用于全文搜索的, 而keyword用于关键词搜索.spa
新的默认类型
作了这个类型分解以后, 咱们对string字段的默认dynamic mappings 也作了改变. 在之前刚接接触ElasticSearch时, 若是须要对某个字段的全部取值作聚合, 你不得不对这些数据重作索引. 假如你正在处理的文档中包含一个city
字段. 对这个字段作聚合的话会分别给出new
和york
的总数, 而非咱们一般指望的New York
的总数.让人沮丧的是为了达到咱们但愿的结果, 咱们必须对这个字段从新进行索引..net
为了避免让事情变得这么糟糕, ElasticSearch决定从Logstash中借取思路: 字符串将默认被同时映射成text
和keyword
类型. 例如对下面的文档进行索引后:code
{ "foo": "bar" }
ElasticSearch将会为你建立下面的动态映射(dynamic mappings):blog
{ "foo": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } }
固然, 基于这个映射你便可以在foo
字段上进行全文搜索, 也能够经过foo.keyword
字段实现关键词搜索及数据聚合.索引
禁用这个特性也很方便: 你只须要在定义mapping时显式声明字符串字段的类型或者使用一个动态模板(dynamic template)
来匹配你全部的字符串字段便可. 例如经过下面的dynamic template
就能够恢复到在ElasticSearch 2.x中使用的dynamic template的效果:ci
{ "match_mapping_type": "string", "mapping": { "type": "text" } }
如何迁移到新版本
一般, 迁移工做是很是容易的. 之前映射到analyzed
的字符串的字段:
{ "foo": { "type": "string", "index": "analyzed" } }
现在只要映射为text
便可:
{ "foo": { "type": "text", "index": true } }
之前被定义为not_analyzed
的字符串字段:
{ "foo": { "type": "string", "index": "not_analyzed" } }
也只须要被定义为keyword
便可:
{ "foo": { "type": "keyword", "index": true } }
如上所述, string
字段被从新定义为text
和keyword
字段. 对于上面的index
属性, 由于在新的定义中咱们不须要三种状态(在之前的string
定义中能够是analyzed
, not_analyzed
和no
), 因此只简单的定义成了boolean值, 以告知ElasticSearch是否可在该字段上进行搜索.
向后兼容
由于大的版本升级自己就充满挑战, 所以咱们尽力不让在在升级ElasticSearch过程当中更新你的mapping字义. 首先, string
字段能够继续在已定义的2.x版本的索引中继续使用, 而当建立新的索引时, ElasticSearch会作些处理以自动把string
映射成等价的text
或keyword
. 若是在你已有的索引模板(index template)中定义有string
字段, 这一点将很是有用, 由于这些模板无须改动便可使用到ElasticSearch 5.x中. 话说回来, 你仍是须要着手作这些模板作些升级, 由于在ElasticSearch 6.0中咱们可能会移除这个向后兼容的逻辑.