Elasticsearch依據我們提供的數據,根據自己的估計,並自動生成相應的mapping。這在很多的時候是非常有用的。 它可以幫我們自動省很多的手動操作,而且在大多數的情況下,Elasticsearch幫我們自動生成的mapping也是有效的。一般來講,如果我們想自己定義自己的mapping的話,如下的步驟將是可取的,也是推薦的方法:
- 把自己的一個數據輸入到Elasticsearch中
- 得到上面輸入數據的mapping,並在此基礎上進行調整,從而得出適合自己數據的mapping
在下面我們以幾個例子來展示幾個我們需要調整的地方。
調整數據類型
我們首先在我們的Kibana中輸入如下的一個命令:
PUT myindex/_doc/1
{
"status_code": 404
}
上面創建一個叫做myindex的索引,它裏面含有一個我們通常見到的HTTP請求的status_code。在這裏我們的文檔的值爲404。我們通過如下的命令來顯示這個myindex的mapping。請記住這個mapping是在第一次數據輸入時,根據我們輸入的數據猜出來的:
GET myindex/_mapping
上面的命令顯示的結果是:
{
"myindex" : {
"mappings" : {
"properties" : {
"status_code" : {
"type" : "long"
}
}
}
}
}
從上面的結果中,我們可以看出來type爲long,意味着這將是一個64bit的數據長度。我們知道HTTP的status_code,通常就是小於1000的數據。這樣一個64 bit的數據顯然浪費存儲空間。如果我們的數據是很少,這個可能並不算是什麼,但是如果我們有海量的數據,那麼這個存儲空間的浪費將是很大的。爲此,我們可以把這個數據類型修改爲short類型的, 也就是16 bit:
PUT myindex1
{
"mappings": {
"properties": {
"status_code": {
"type": "short"
}
}
}
}
在上面,我們創建的myindex1的mapping裏定義status_code爲short類型。
如果你之前看過我的另外一篇文章“開始使用Elasticsearch (2)”,我們在那裏也調整一個geo_point的數據類型。比如:
PUT twitter/_doc/1
{
"user": "zhangsan",
"location": {
"lat": "39.970718",
"lon": "116.325747"
}
}
我們看看Elasticsearch幫我們生產的數據類型:
GET twitter/_mapping
{
"twitter" : {
"mappings" : {
"properties" : {
"location" : {
"properties" : {
"lat" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"lon" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"user" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
顯然,在上面我們可以看到lat及lon都被估算爲text類型,而且是一個multi-field的數據類型,這顯然不是我們所需要的。另外,我們的user類型,我們並不想它是一個text類型的。那麼我們可以作如下的調整:
PUT twitter1
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
},
"user": {
"type": "keyword"
}
}
}
}
在上面的twitter1中,我們可以看出來調整後的location類型爲geo_point的數據類型,而user也變成了我們所希望的keyword類型。
動態的mapping並不總是優化的
針對一個浮點數來說:
PUT my_index/_doc/1
{
"price": 1.99
}
我們可以得到它的mapping:
GET my_index/_mapping
{
"my_index" : {
"mappings" : {
"properties" : {
"price" : {
"type" : "float"
}
}
}
}
}
從上面我們可以看出來,price的數據類型是一個float類型。對於大多數的情況來說,這個應該沒有問題。但是在實際的應用中,我們可以把這個float數據類型轉換爲scaled float數據類型。Scaled float由long數據類型來支持。long數據類型在Lucene裏可以被更加有效地壓縮,從而節省存儲的空間。在使用scaled float數據類型時,你必須使用scaling_factore來配置它的精度:
PUT my_index1/_doc/1
{
"mappings": {
"properties": {
"price": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
}
在上面我們定義price類型爲scaled_float數據類型,並定義scaling_factor爲100。這樣我們的數據,比如1.99剛好可以在乘以100變爲199,從而成爲一個整型數。
經過這樣的改造後,我們可以試試重新在my_index1裏輸入一個文檔:
PUT my_index1/_doc/1
{
"price": 1.99
}
我們通過如下的方法來查詢這個數據:
GET my_index1/_doc/1
返回的結果是:
{
"_index" : "my_index1",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"_seq_no" : 1,
"_primary_term" : 1,
"found" : true,
"_source" : {
"price" : 1.99
}
}
從上面我們可以看出來,儘管我們修改了我們的數據類型,但是我們返回的數據還是對的。