官方原文鏈接:https://www.elastic.co/cn/blog/strings-are-dead-long-live-strings
轉載原文連接:https://segmentfault.com/a/1190000008897731
Text vs. keyword
隨着ElasticSearch 5.0的到來, 同時也迎來了該版本的重大特性之一: 移除了string
類型. 這個變動的根本原因是string
類型會給我們帶來很多困惑: 因為ElasticSearch對字符串擁有兩種完全不同的搜索方式. 你可以按照整個文本進行匹配, 即關鍵詞搜索(keyword search), 也可以按單個字符匹配, 即全文搜索(full-text search). 對ElasticSearch稍有了解的人都知道, 前者的字符串被稱為not-analyzed
字符, 而后者被稱作analyzed
字符串.
事實上, 同一種類型用於應對兩種不同的使用場景是會讓人崩潰的, 因為有些選項只對其一的場景設置有效.例如position_increment_gap
對not-analyzed
字符就不會起作用, 而像ignore_above
對於analyzed
字符串就很難區分它到底是對整個字符串的值有效還是對單獨的每個分詞有效(在這種場景, ignore_above確實只對整個字符串值有效, 而對單個分詞的限制可以使用limit
設置).
為了避免上述尷尬, string
字段被拆分成兩種新的數據類型: text
用於全文搜索的, 而keyword用於關鍵詞搜索.
新的默認類型
做了這個類型分解之后, 我們對string字段的默認dynamic mappings 也做了改變. 在以前剛接接觸ElasticSearch時, 如果需要對某個字段的所有取值做聚合, 你不得不對這些數據重做索引. 假如你正在處理的文檔中包含一個city
字段. 對這個字段做聚合的話會分別給出new
和york
的總數, 而非我們通常期望的New York
的總數.讓人沮喪的是為了達到我們希望的結果, 我們必須對這個字段重新進行索引.
為了不讓事情變得這么糟糕, ElasticSearch決定從Logstash中借取思路: 字符串將默認被同時映射成text
和keyword
類型. 例如對下面的文檔進行索引后:
{ "foo": "bar" }
ElasticSearch將會為你創建下面的動態映射(dynamic mappings):
{ "foo": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } }
當然, 基於這個映射你即可以在foo
字段上進行全文搜索, 也可以通過foo.keyword
字段實現關鍵詞搜索及數據聚合.
禁用這個特性也很方便: 你只需要在定義mapping時顯式聲明字符串字段的類型或者使用一個動態模板(dynamic template)
來匹配你所有的字符串字段即可. 例如通過下面的dynamic template
就可以恢復到在ElasticSearch 2.x中使用的dynamic template的效果:
{ "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中我們可能會移除這個向后兼容的邏輯.