1. 程式人生 > >Elasticsearch 6.x 和 5.x 字串型別的差別

Elasticsearch 6.x 和 5.x 字串型別的差別

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

欄位. 對這個欄位做聚合的話會分別給出newyork的總數, 而非我們通常期望的New York的總數.讓人沮喪的是為了達到我們希望的結果, 我們必須對這個欄位重新進行索引.

為了不讓事情變得這麼糟糕, ElasticSearch決定從Logstash中借取思路: 字串將預設被同時對映成textkeyword型別. 例如對下面的文件進行索引後:

{
    "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欄位被重新定義為textkeyword欄位. 對於上面的index屬性, 因為在新的定義中我們不需要三種狀態(在以前的string定義中可以是analyzednot_analyzedno), 所以只簡單的定義成了boolean值, 以告知ElasticSearch是否可在該欄位上進行搜尋.

向後相容

因為大的版本升級本身就充滿挑戰, 因此我們盡力不讓在在升級ElasticSearch過程中更新你的mapping字義. 首先, string欄位可以繼續在已定義的2.x版本的索引中繼續使用, 而當建立新的索引時, ElasticSearch會做些處理以自動把string對映成等價的textkeyword. 如果在你已有的索引模板(index template)中定義有string欄位, 這一點將非常有用, 因為這些模板無須改動即可使用到ElasticSearch 5.x中. 話說回來, 你還是需要著手做這些模板做些升級, 因為在ElasticSearch 6.0中我們可能會移除這個向後相容的邏輯.



轉載地址