Elasticsearch:mapping定製

Elasticsearch依據我們提供的數據,根據自己的估計,並自動生成相應的mapping。這在很多的時候是非常有用的。 它可以幫我們自動省很多的手動操作,而且在大多數的情況下,Elasticsearch幫我們自動生成的mapping也是有效的。一般來講,如果我們想自己定義自己的mapping的話,如下的步驟將是可取的,也是推薦的方法:

  1. 把自己的一個數據輸入到Elasticsearch中
  2. 得到上面輸入數據的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
  }
}

從上面我們可以看出來,儘管我們修改了我們的數據類型,但是我們返回的數據還是對的。

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章