官方原文連接: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中咱們可能會移除這個向後兼容的邏輯.