Elasticsearch 參考指南(刪除映射類型)

刪除映射類型

在Elasticsearch 7.0.0或更高版本中建立的索引再也不接受 _default_映射,索引在6.x中建立將繼續在Elasticsearch 6.x中運行,類型在api 7.0中是不受支持的,它會中斷對索引建立、put映射、get映射、put模板、get模板和get字段映射API的更改。

什麼是映射類型?

自從第一次發佈Elasticsearch以來,每一個文檔都存儲在一個索引中,並分配了一個映射類型,映射類型用於表示被索引的文檔或實體的類型,例如twitter索引可能具備user類型和tweet類型。數據庫

每一個映射類型均可以有本身的字段,所以user類型能夠有full_name字段、user_name字段和email字段,而tweet類型能夠有content字段、tweeted_at字段,和user類型同樣,還有user_name字段。segmentfault

每一個文檔都有一個包含類型名稱的_type元字段,經過在URL中指定類型名稱,能夠將搜索限制爲一個或多個類型:api

GET twitter/user,tweet/_search
{
  "query": {
    "match": {
      "user_name": "kimchy"
    }
  }
}

_type字段與文檔的_id相結合生成_uid字段,所以具備相同_id的不一樣類型的文檔能夠存在於一個索引中。app

還使用映射類型在文檔之間創建父子關係,所以類型爲question的文檔能夠是類型爲answer的文檔的父文檔。ui

爲何要刪除映射類型?

最初,討論了「索引」相似於SQL數據庫中的「數據庫」,以及「類型」等價於「表」。code

這是一個錯誤的類比,致使了錯誤的假設,在SQL數據庫中,表是相互獨立的,一個表中的列與另外一個表中具備相同名稱的列沒有關係,這與映射類型中的字段不一樣。繼承

在Elasticsearch索引中,不一樣映射類型中具備相同名稱的字段在內部由相同的Lucene字段支持,換句話說,使用上面的示例,user類型中的user_name字段存儲在與tweet類型中的user_name字段徹底相同的字段中,並且兩個user_name字段在這兩種類型中必須具備相同的映射(定義)。索引

例如,當你想要刪除一個類型中的date字段和同一個索引中的另外一個類型中的boolean字段時,這可能會致使失敗。ip

最重要的是,存儲在同一索引中具備不多或沒有共同字段的不一樣實體會致使數據稀疏,並影響Lucene有效壓縮文檔的能力。文檔

基於這些緣由,決定將映射類型的概念從Elasticsearch中移除。

映射類型的替代方案

每種文檔類型的索引

第一種選擇是爲每一個文檔類型都有一個索引,你能夠將tweets存儲爲tweetsuser索引,而不是將tweetsusers存儲在單個twitter索引中,索引之間是徹底獨立的,所以索引之間不存在字段類型的衝突。

這種方法有兩個好處:

  • 數據更多是密集的,所以受益於Lucene中使用的壓縮技術。
  • 用於在全文搜索中得分的統計術語更可能準確,由於同一索引中的全部文檔都表示一個實體。

每一個索引均可以根據它將包含的文檔數量適當調整大小:你能夠爲users使用較少的主碎片,而爲tweet使用較多的主碎片。

自定義類型字段

固然,集羣中能夠存在多少主碎片是有限制的,所以你可能不但願爲了一個只有幾千個文檔的集合而浪費整個碎片,在本例中,你能夠實現本身的自定義類型字段,其工做方式與舊的_type相似。

讓咱們以上面的user/tweet爲例,最初,工做流應該是這樣的:

PUT twitter
{
  "mappings": {
    "user": {
      "properties": {
        "name": { "type": "text" },
        "user_name": { "type": "keyword" },
        "email": { "type": "keyword" }
      }
    },
    "tweet": {
      "properties": {
        "content": { "type": "text" },
        "user_name": { "type": "keyword" },
        "tweeted_at": { "type": "date" }
      }
    }
  }
}

PUT twitter/user/kimchy
{
  "name": "Shay Banon",
  "user_name": "kimchy",
  "email": "shay@kimchy.com"
}

PUT twitter/tweet/1
{
  "user_name": "kimchy",
  "tweeted_at": "2017-10-24T09:00:00Z",
  "content": "Types are going away"
}

GET twitter/tweet/_search
{
  "query": {
    "match": {
      "user_name": "kimchy"
    }
  }
}

你能夠經過添加自定義類型字段來實現相同的功能,以下所示:

PUT twitter
{
  "mappings": {
    "_doc": {
      "properties": {
        "type": { "type": "keyword" }, 
        "name": { "type": "text" },
        "user_name": { "type": "keyword" },
        "email": { "type": "keyword" },
        "content": { "type": "text" },
        "tweeted_at": { "type": "date" }
      }
    }
  }
}

PUT twitter/_doc/user-kimchy
{
  "type": "user", 
  "name": "Shay Banon",
  "user_name": "kimchy",
  "email": "shay@kimchy.com"
}

PUT twitter/_doc/tweet-1
{
  "type": "tweet", 
  "user_name": "kimchy",
  "tweeted_at": "2017-10-24T09:00:00Z",
  "content": "Types are going away"
}

GET twitter/_search
{
  "query": {
    "bool": {
      "must": {
        "match": {
          "user_name": "kimchy"
        }
      },
      "filter": {
        "match": {
          "type": "tweet" 
        }
      }
    }
  }
}
  • 顯式type字段替代了隱式_type字段。

沒有映射類型的父/子關係

之前,父—子關係表示爲將一個映射類型表示爲父,將一個或多個其餘映射類型表示爲子,沒有類型,咱們就不能再使用這種語法,除了表示文檔之間關係的方式已更改成使用新的join字段外,父—子特性將繼續像之前同樣工做。

刪除映射類型的時間表

對於用戶來講,這是一個巨大的變化,因此已經嘗試讓它儘量地不那麼痛苦,更改將按以下方式進行:

Elasticsearch 5.6.0

  • 在索引上設置index.mapping.single_type: true將啓用在6.0中強制執行的單類型/索引行爲。
  • 在5.6中建立的索引中可使用父—子join字段替換。

Elasticsearch 6.x

  • 在5.x中建立索引將繼續在6.x中運行就像5.x。
  • 索引在6.x中建立只容許每一個索引使用單一類型,類型可使用任何名稱,但只能有一個,首選的類型名稱是_doc,所以索引API具備與7.0中相同的路徑:PUT {index}/_doc/{id} and POST {index}/_doc
  • _type名稱不能再與_id組合以造成_uid字段,_uid字段已成爲_id字段的別名。
  • 新的索引再也不支持舊式的父/子索引,而是應該使用join字段。
  • _default_映射類型已棄用。
  • 在6.8中,索引建立、索引模板和映射API支持查詢字符串參數(include_type_name),該參數指示請求和響應是否應該包含類型名稱。它默認爲true,應該設置爲一個顯式值,以便準備升級到7.0,未設置include_type_name將致使一個棄用警告,沒有顯式類型的索引將使用虛擬類型名稱_doc

Elasticsearch 7.x

  • 在請求中指定類型已棄用,例如,索引文檔再也不須要文檔type,對於顯式id,新的索引API是PUT {index}/_doc/{id},對於自動生成的id則是POST {index}/_doc,注意,在7.0中,_doc是路徑的一個永久部分,它表示端點名稱,而不是文檔類型。
  • 索引建立、索引模板和映射API中的include_type_name參數默認爲false,徹底設置該參數將致使一個棄用警告。
  • 刪除_default_映射類型。

Elasticsearch 8.x

  • 再也不支持在請求中指定類型。
  • 刪除include_type_name參數。

將多類型索引遷移到單類型

Reindex API可用於將多類型索引轉換爲單類型索引,下面的例子能夠在Elasticsearch 5.6或Elasticsearch 6.x中使用,在6.x,不須要指定index.mapping.single_type做爲默認值。

每種文檔類型的索引

第一個示例將twitter索引拆分爲tweets索引和users索引:

PUT users
{
  "settings": {
    "index.mapping.single_type": true
  },
  "mappings": {
    "_doc": {
      "properties": {
        "name": {
          "type": "text"
        },
        "user_name": {
          "type": "keyword"
        },
        "email": {
          "type": "keyword"
        }
      }
    }
  }
}

PUT tweets
{
  "settings": {
    "index.mapping.single_type": true
  },
  "mappings": {
    "_doc": {
      "properties": {
        "content": {
          "type": "text"
        },
        "user_name": {
          "type": "keyword"
        },
        "tweeted_at": {
          "type": "date"
        }
      }
    }
  }
}

POST _reindex
{
  "source": {
    "index": "twitter",
    "type": "user"
  },
  "dest": {
    "index": "users"
  }
}

POST _reindex
{
  "source": {
    "index": "twitter",
    "type": "tweet"
  },
  "dest": {
    "index": "tweets"
  }
}

自定義類型字段

下一個示例添加一個自定義類型字段,並將其設置爲原始_type的值,它還將類型添加到_id中,以防有任何不一樣類型的文檔具備衝突的id

PUT new_twitter
{
  "mappings": {
    "_doc": {
      "properties": {
        "type": {
          "type": "keyword"
        },
        "name": {
          "type": "text"
        },
        "user_name": {
          "type": "keyword"
        },
        "email": {
          "type": "keyword"
        },
        "content": {
          "type": "text"
        },
        "tweeted_at": {
          "type": "date"
        }
      }
    }
  }
}


POST _reindex
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  },
  "script": {
    "source": """
      ctx._source.type = ctx._type;
      ctx._id = ctx._type + '-' + ctx._id;
      ctx._type = '_doc';
    """
  }
}

7.0中的無類型API

在Elasticsearch 7.0中,每一個API都支持無類型請求,指定類型將產生一個棄用警告。

即便目標索引包含自定義類型,無類型API也能夠工做,例如,若是索引具備自定義類型名稱 my_type,則可使用無類型 index調用向其添加文檔,並使用無類型 get調用加載文檔。

索引API

索引建立、索引模板和映射API支持一個新的include_type_name URL參數,該參數指定請求和響應中的映射定義是否應該包含類型名稱,版本6.8中的參數默認爲true,以匹配在映射中使用類型名稱的7.0以前的行爲,它在7.0版本中默認爲false,將在8.0版本中刪除。

它應該在6.8中明確設置,以便準備升級到7.0,爲了不6.8中的棄用警告,能夠將參數設置爲truefalse,在7.0中,設置include_type_name將致使一個棄用警告。

查看一些與Elasticsearch交互的例子,這個選項設置爲false

PUT index?include_type_name=false
{
  "mappings": {
    "properties": { 
      "foo": {
        "type": "keyword"
      }
    }
  }
}
  • 映射直接包含在mappings鍵下,沒有類型名稱。
PUT index/_mappings?include_type_name=false
{
  "properties": { 
    "bar": {
      "type": "text"
    }
  }
}
  • 映射直接包含在mappings鍵下,沒有類型名稱。
GET index/_mappings?include_type_name=false

上面的調用返回:

{
  "index": {
    "mappings": {
      "properties": { 
        "foo": {
          "type": "keyword"
        },
        "bar": {
          "type": "text"
        }
      }
    }
  }
}
  • 映射直接包含在mappings鍵下,沒有類型名稱。

文檔API

在7.0中,必須使用{index}/_doc路徑調用索引API,以便自動生成_id,使用顯式id調用{index}/_doc/{id}

PUT index/_doc/1
{
  "foo": "baz"
}
{
  "_index": "index",
  "_id": "1",
  "_type": "_doc",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}

相似地,getdelete API使用路徑{index}/_doc/{id}

GET index/_doc/1
在7.0中, _doc表示端點名稱,而不是文檔類型, _doc組件是文檔 indexgetdelete API路徑的永久部分,在8.0中不會被刪除。

對於同時包含類型和端點名(如_update)的API路徑,在7.0中端點將當即跟隨索引名:

POST index/_update/1
{
    "doc" : {
        "foo" : "qux"
    }
}

GET /index/_source/1

類型也不該該再出如今請求體中,下面的bulk索引示例省略了URL和單個批量命令中的類型:

POST _bulk
{ "index" : { "_index" : "index", "_id" : "3" } }
{ "foo" : "baz" }
{ "index" : { "_index" : "index", "_id" : "4" } }
{ "foo" : "qux" }

搜索API

在調用諸如_search_msearch_explain之類的搜索API時,URL中不該該包含類型,此外,_type字段不該該用於查詢、聚合或腳本。

響應中的類型

文檔和搜索API將繼續在響應中返回_type鍵,以免中斷響應解析,然而,鍵被認爲是不同意的,不該該再被引用,類型將在8.0中從響應中徹底刪除。

注意,當使用廢棄的類型化API時,索引的映射類型將做爲正常返回,可是無類型API將在響應中返回虛擬類型_doc,例如,下面的無類型get調用老是返回_doc做爲類型,即便映射有一個像my_type這樣的自定義類型名:

PUT index/my_type/1
{
  "foo": "baz"
}

GET index/_doc/1
{
    "_index" : "index",
    "_type" : "_doc",
    "_id" : "1",
    "_version" : 1,
    "_seq_no" : 0,
    "_primary_term" : 1,
    "found": true,
    "_source" : {
        "foo" : "baz"
    }
}

索引模版

建議經過將include_type_name設置爲false來從新添加索引模板,使其無類型,在底層,無類型模板在建立索引時將使用虛擬類型_doc

若是將無類型模板用於類型化索引建立調用,或者將類型化模板用於無類型索引建立調用,則仍將應用模板,但索引建立調用將決定是否應該有類型。例如在下面的示例中,index-1-01將具備一個類型,儘管它匹配一個沒有類型的模板,而index-2-01將具備無類型,儘管它匹配一個定義了類型的模板,index-1-01index-2-01都將從匹配的模板中繼承foo字段。

PUT _template/template1
{
  "index_patterns":[ "index-1-*" ],
  "mappings": {
    "properties": {
      "foo": {
        "type": "keyword"
      }
    }
  }
}

PUT _template/template2?include_type_name=true
{
  "index_patterns":[ "index-2-*" ],
  "mappings": {
    "type": {
      "properties": {
        "foo": {
          "type": "keyword"
        }
      }
    }
  }
}

PUT index-1-01?include_type_name=true
{
  "mappings": {
    "type": {
      "properties": {
        "bar": {
          "type": "long"
        }
      }
    }
  }
}

PUT index-2-01
{
  "mappings": {
    "properties": {
      "bar": {
        "type": "long"
      }
    }
  }
}

在隱式索引建立的狀況下,由於文檔在索引中被索引,而索引還不存在,因此老是使用模板,這一般不是一個問題,由於無類型索引調用要處理有類型的索引。

混合版本的集羣

在由6.8和7.0節點組成的集羣中,應該在索引建立之類的索引API中指定參數include_type_name,這是由於參數在6.8和7.0之間有不一樣的默認值,因此相同的映射定義對兩個節點版本都無效。

諸如bulkupdate之類的無類型文檔API僅在7.0版本時可用,不能用於6.8節點,對於執行文檔查找的查詢的無類型版本,如terms,也是如此。

相關文章
相關標籤/搜索