前言
我們已經自由奔放夠了!
我們應該知道,在關系型數據庫中,必須先定義表結構,才能插入數據,並且,表結構不會輕易改變。而我們呢,我們怎么玩elasticsearch的呢:
PUT t1/doc/1
{
"name": "小黑"
}
PUT t1/doc/2
{
"name": "小白",
"age": 18
}
文檔的字段可以是任意的,原本都是name
字段,突然來個age
。還要elasticsearch自動去猜,哦,可能是個long
類型,然后加個映射!之后發什么什么?肯定是:猜猜猜,猜你妹!
難道你不想知道elasticsearch內部是怎么玩的嗎?
當我們執行上述第一條PUT
命令后,elasticsearch到底是怎么做的:
GET t1
結果:
{
"t1" : {
"aliases" : { },
"mappings" : {
"doc" : {
"properties" : {
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1553334893136",
"number_of_shards" : "5",
"number_of_replicas" : "1",
"uuid" : "lHfujZBbRA2K7QDdsX4_wA",
"version" : {
"created" : "6050499"
},
"provided_name" : "t1"
}
}
}
}
由返回結果可以看到,分為兩大部分,第一部分關於t1
索引類型相關的,包括該索引是否有別名aliases
,然后就是mappings
信息,包括索引類型doc
,各字段的詳細映射關系都收集在properties
中。
另一部分是關於索引t1
的settings
設置。包括該索引的創建時間,主副分片的信息,UUID等等。
我們再執行第二條PUT
命令,再查看該索引是否有什么變化,返回結果如下:
{
"t1" : {
"aliases" : { },
"mappings" : {
"doc" : {
"properties" : {
"age" : {
"type" : "long"
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1553334893136",
"number_of_shards" : "5",
"number_of_replicas" : "1",
"uuid" : "lHfujZBbRA2K7QDdsX4_wA",
"version" : {
"created" : "6050499"
},
"provided_name" : "t1"
}
}
}
}
由返回結果可以看到,settings
沒有變化,只是mappings
中多了一條關於age
的映射關系,這一切都是elasticsearch自動的,但特定的場景下,需要我們更多的設置。
所以,接下來,我們研究一下mappings
這個小老弟,到底是怎么回事!
映射是什么?
其實,映射mappings
沒那么神秘!說白了,就相當於原來由elasticsearch自動幫我們定義表結構。現在,我們要自己來了,旨在創建索引的時候,有更多定制的內容,更加的貼合業務場景。OK,坐好了,開車!
elasticsearch
中的映射用來定義一個文檔及其包含的字段如何存儲和索引的過程。例如,我們可以使用映射來定義:
- 哪些字符串應該被視為全文字段。
- 哪些字段包含數字、日期或者地理位置。
- 定義日期的格式。
- 自定義的規則,用來控制動態添加字段的的映射。
身為吃瓜群眾的小老弟,不懂沒關系,往下走!
映射類型
每個索引都有一個映射類型(這話必須放在elasticsearch6.x版本后才能說,之前版本一個索引下有多個類型),它決定了文檔將如何被索引。
映射類型有:
- 元字段(meta-fields):元字段用於自定義如何處理文檔關聯的元數據,例如包括文檔的
_index
、_type
、_id
和_source
字段。 - 字段或屬性(field or properties):映射類型包含與文檔相關的字段或者屬性的列表。
還不懂,沒關系,繼續往下走!
字段的數據類型
- 簡單類型,如文本(
text
)、關鍵字(keyword
)、日期(date
)、整形(long
)、雙精度(double
)、布爾(boolean
)或ip
。 - 可以是支持
JSON
的層次結構性質的類型,如對象或嵌套。 - 或者一種特殊類型,如
geo_point
、geo_shape
或completion
。
為了不同的目的,以不同的方式索引相同的字段通常是有用的。例如,字符串字段可以作為全文搜索的文本字段進行索引,也可以作為排序或聚合的關鍵字字段進行索引。或者,可以使用標准分析器、英語分析器和法語分析器索引字符串字段。
這就是多字段的目的。大多數數據類型通過fields參數支持多字段。
映射約束
在索引中定義太多的字段有可能導致映射爆炸!因為這可能會導致內存不足以及難以恢復的情況,為此。我們可以手動或動態的創建字段映射的數量:
- index.mapping.total_fields.limit:索引中的最大字段數。字段和對象映射以及字段別名都計入此限制。默認值為1000。
- index.mapping.depth.limit:字段的最大深度,以內部對象的數量來衡量。例如,如果所有字段都在根對象級別定義,則深度為1.如果有一個子對象映射,則深度為2,等等。默認值為20。
- index.mapping.nested_fields.limit:索引中嵌套字段的最大數量,默認為50.索引1個包含100個嵌套字段的文檔實際上索引101個文檔,因為每個嵌套文檔都被索引為單獨的隱藏文檔。
一個簡單的映射示例
PUT mapping_test1
{
"mappings": {
"test1":{
"properties":{
"name":{"type": "text"},
"age":{"type":"long"}
}
}
}
}
上例中,我們在創建索引PUT mapping_test1
的過程中,為該索引定制化類型(設計表結構),添加一個映射類型test1
;指定字段或者屬性都在properties
內完成。
GET mapping_test1
通過GET
來查看。
{
"mapping_test1" : {
"aliases" : { },
"mappings" : {
"test1" : {
"properties" : {
"age" : {
"type" : "long"
},
"name" : {
"type" : "text"
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1550469220778",
"number_of_shards" : "5",
"number_of_replicas" : "1",
"uuid" : "7I_m_ULRRXGzWcvhIZoxnQ",
"version" : {
"created" : "6050499"
},
"provided_name" : "mapping_test1"
}
}
}
}
返回的結果中你肯定很熟悉!映射類型是test1
,具體的屬性都被封裝在properties
中。而關於settings
的配置,我們暫時不管它。
我們為這個索引添加一些數據:
put mapping_test1/test1/1
{
"name":"張開嘴",
"age":16
}
上例中,mapping_test1
是之前創建的索引,test1
為之前自定義的mappings
類型。字段是之前創建好的name
和age
。
GET mapping_test1/test1/_search
{
"query": {
"match": {
"age": 16
}
}
}
上例中,我們通過age
條件查詢。
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "mapping_test1",
"_type" : "test1",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "張開嘴",
"age" : 16
}
}
]
}
}
返回了預期的結果信息。
歡迎斧正,that's all