ES--刪除映射類型


一 前言

官方解釋:https://www.elastic.co/guide/en/elasticsearch/reference/6.0/removal-of-types.html

在elasticsearch6.0.0或更高的版本中創建索引僅能包含單個映射類型。在具有多種映射類型的5.x版本中創建的索引將繼續像以前一樣在elasticsearch6.x中運行。類型將在elasticsearch7.0.0中的API中棄用,並在8.0.0中完全刪除。

二 什么是映射類型?

從elasticsearch發布以來,每個文檔都存儲在單個索引中並分配了單個映射類型。映射類型用於表示要編制索引的文檔或實體的類型。例如微博(twitter)索引可能具有用戶(user)類型和推文(tweet)兩個類型。

每種映射類型都可以有自己的字段,因此用戶(user)類型可能有full_nameuser_nameemail字段;而推文(tweet)類型可能有contenttweet_at字段和用戶(user)類型的user_name字段。
每個文檔都有一個_type包含類型名稱的元字段,通過在URL中指定類型名稱,搜索可以限制為一種或多種類型:

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

_type字段與文檔組合_id以生成_uid字段,因此具有相同類型的文檔_id可以存儲在單個索引中。
映射類型也用於在文檔中建立父子關系,因此類型的文檔question可以是類型文檔的父類answer
扯了半天淡,一切不都是挺好的嘛?那還為啥要刪除映射類型呢?

三 為什么要刪除映射類型?

最初(其實到現在),為了便於理解elasticsearch的數據組織,通常拿elasticsearch和關系型數據庫做對比,比如我們談到一個es索引(index)時,通常將它比喻為類似於SQL數據庫中的database,而類型(type)等同於SQL數據庫中的表。
這真是一個糟糕的比喻!讓我們有了錯誤理解。因為在SQL數據庫中,表彼此獨立,一個表中的字段與另一個表中具有相同名稱的字段無關,而映射類型中的字段不是這種情況。
在elasticsearch的索引中,不同映射類型具有相同名稱的字段在內部由相同的Lucene字段支持。換句話說,使用上面的示例,用戶(user)類型中的user_name字段存儲在和推文(tweet)類型中的user_name字段完全相同的字段中,而且兩種類型中的user_name字段必須具有相同的映射(定義)。
當我們希望刪除一個類型的日期字段和同一個索引中另一個類型的布爾字段時,這可能會導致挫敗感(可以理解為刪除失敗)。
最重要的是,在同一索引中存儲具有很少或沒有共同字段的不同實體會導致稀疏數據並干擾Lucene有效壓縮文檔的能力。
出於這些原因,我們決定從elasticsearch中刪除映射類型的概念。

四 映射類型的替代方法

4.1 將映射類型分開存儲在索引中

第一種方法是每個文檔類型都有一個索引,例如微博(twitter)索引中,我們可以將推文(tweet)類型和用戶(user)類型分開,分別存儲在獨立的索引中。這樣兩個相互的索引就不會引起字段沖突了。
這中方法有兩個好處:

  • 數據更可能是密集的,因此受益於Lucene中使用的壓縮技術。
  • 用於全文搜索評分的詞條統計將會更精確,應為同一索引中的所有文檔都代表單個實體。

每個索引的大小可以根據其包含的文檔數量進行適當的調整,比如我們為用戶(user)類型分配較少的主分片,而為推文(tweet)類型分配較多的主分片。

4.2 自定義類型字段回到頂部

當然了,集群中可以存儲多少個主分片是有限制的,我們不希望僅為幾千個文檔的集合而浪費整個分片。在這種情況下,我們可以實現自己的自定義type字段,該字段的工作方式與舊的_type相似。
還是上面微博(twitter)例子,最初,它的映射類型看起來是這樣的:

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

PUT twitter/user/kimchy
{
  "name":"狗子",
  "user_name":"二狗子",
  "email":"dog@twodog.com"
}

PUT twitter/tweet/1
{
  "name":"kimchy",
  "tweet_ad":"2019-04-30T10:26:20Z",
  "content":"單身狗求包養"
}


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

如上示例,請在5.x及以下版本測試
我們也可以通過添加自定義type字段來實現相同目的:

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

PUT twitter/doc/user-kimchy
{
  "type":"user",
  "name":"狗子",
  "user_name":"二狗子",
  "email":"dog@twodog.com"
}


PUT twitter/doc/tweet-1
{
  "type":"tweet",
  "user_name":"kimchy",
  "tweet_at":"2019-04-30T10:26:20Z",
  "content":"單身狗求包養"
}

GET twitter/_search
{
  "query": {
    "bool": {
      "must":[
        {
          "match": {
            "user_name": "kimchy"
          }
        }
      ],
      "filter": {
        "match":{
          "type":"tweet"
        }
      }
    }
  }
}

上述示例6.5.4版本運行無誤。

五 沒有映射類型的父/子

以前,通過將一個映射類型設置為父級,將一個或多個其他映射類型設置為子級來表示父子關系。現在,沒有了多類型,我們就不能再使用這種語法了。除了表示文檔之間的關系方式已改為使用新的join字段之外,父子特征將繼續像以前一樣運行。

六 刪除映射類型的計划

這個刪除映射類型的計划,對於用戶來說是一個很大的變化,所以我們試圖讓它盡可能輕松,更改將如下所示:
在elasticsearch5.6.0中:

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

在elasticsearch6.x中:

  • 在5.x中創建的索引將繼續在6.x中運行,就像在5.x中一樣。
  • 在6.x中創建的索引僅允許每個索引使用單一類型,任何字段都可以用於該類型,但必須是唯一的。
  • _type名稱可以不再與_id組合形成_uid字段,_uid字段已成為_id字段的別名。
  • 新索引不再支持舊的父/子關系,而是應該使用連接字段。
  • 不推薦使用_default_mapping類型。
  • 在6.7中,索引創建、索引模板和映射API支持查詢字符串參數(include_type_name),該參數僅表示請求和響應是否應該包含類型名稱,默認為true,應該設置為一個顯式值,以便准備升級到7.0。未設置include_type_name將導致一個棄用警告,沒有顯式類型的索引將使用默認的類型名稱_doc

在elasticsearch7.x中:

  • 不推薦在請求中指定類型。例如,索引文檔不再需要文檔類型。對於自動生成的id,新的索引API在顯式ids和POST {index_name}/_doc的情況下是PUT {index_name}/_doc/{id}
  • 索引創建,索引模板和映射API中的include_type_name參數將默認為false,未設置參數將導致啟動警告。
  • 刪除了_default_mapping類型。

在elasticsearch8.x中:

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

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

Reindex API可用於將多類型索引轉換為單類型索引。下面的例子可以在Elasticsearch 5.6或Elasticsearch 6.x中使用。在6.x中,不需要指定index.mapping。默認為單一類型。

7.1 每種文檔類型的索引

第一個示例將微博(twitter)索引拆分為推文(tweets)索引和用戶(users)索引:

PUT users
{
  "mappings": {
    "user":{
      "properties":{
        "name":{
          "type":"text"
        },
        "user_name":{
          "type":"keyword"
        },
        "email":{
          "type":"keyword"
        }
      }
    }
  }
}

PUT tweets
{
  "mappings": {
    "tweet":{
      "properties":{
        "content":{
          "type":"text"
        },
        "user_name":{
          "type":"keyword"
        },
        "tweet_at":{
          "type":"date"
        }
      }
    }
  }
}

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

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

上述代碼在6.5.4版本中運行無誤。
上述的示例意思是,在之前我們在微博(twitter)索引中,有兩個類型(tweet和user)。現在要將兩個類型分開,成為獨立的索引。所以,首先先創建出各自的索引(tweets和users),然后通過POST _reindex來完成遷移工作。

7.2 自定義類型字段

第二個示例添加自自定義的type字段,並將其設置為原始值_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"
        },
        "tweet_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";
      
    """
  }
}

上述代碼在6.5.4版本運行無誤。

八 總結

總之,通篇看下來,如果對elasticsearch,尤其是各版本不太了解的話,這篇文檔看着索然無味!重要的是看不懂,如果我們是新手,接觸elasticsearch的時候,就是從6.x版本開始的,那只要記得,一個索引下面只能創建一個類型就行了,其中各字段都具有唯一性,如果在創建映射的時候,如果沒有指定文檔類型,那么該索引的默認索引類型是_doc,不指定文檔id則會內部幫我們生成一個id字符串。其他的,who care?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM