Elasticsearch動態映射與日期類型
JSon沒有日期類型,但Elasticsearch能自動爲我們映射日期字段。如果結合日期字段命名約定可以幫我我們準確實現動態映射。
1. 動態映射
Elasticsearch的動態映射特性可以實現根據字段值自動映射字段類型(缺省類型),因此無需顯示定義如何索引、存儲字段,Elasticsearch通過檢查JSon屬性的內容自動推斷類型。請看示例:
如果之前沒有索引myindex
,Elasticsearch會幫助我們做下列工作:
POST /myindex/_doc
{
"content": "Hello World!",
"postDate": "2009-11-15T14:12:12"
}
- 創建索引
myindex
,包括兩個字段content和postDate - 使用json對象內容增加一個文檔
我們來看看Elasticsearch爲我們自動創建索引的映射:
GET myindex/_mapping
結果如下:
{
"myindex" : {
"mappings" : {
"properties" : {
"content" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"postDate" : {
"type" : "date"
}
}
}
}
}
content類型默認爲text,同時生成content.keyword爲keyword類型,同時可以實現全文檢索和精確檢索。postDate爲Date類型。
如果我們通過DELETE /myindex
刪除上面myindex,而用下面的內容添加索引:
POST /myindex/_doc
{
"content": "1985-12-24",
"postDate": "2009-11-15T14:12:12"
}
再次查看映射:
{
"myindex" : {
"mappings" : {
"properties" : {
"content" : {
"type" : "date"
},
"postDate" : {
"type" : "date"
}
}
}
}
}
elasticsearch把content字段也推斷了日期類型。如果現在插入原來的文檔會報異常:
POST /myindex/_doc
{
"content": "Hello World!",
"postDate": "2009-11-15T14:12:12"
}
"caused_by": {
"type": "illegal_argument_exception",
"reason": "failed to parse date field [Hello World!] with format [strict_date_optional_time||epoch_millis]"
}
...
我們試圖將字符串值插入到映射爲日期的字段中,ElasticSearch自然不允許。
雖然這種情況不太可能發生,但發生時會非常惱人,只能通過將所有內容重新索引到新索引中來解決。但幸運的是有許多可能的解決方案。
2. 禁止日期推斷
首先我們可以禁用動態映射時日期推斷。下面示例顯示禁止日期推斷:
PUT /myindex
{
"mappings": {
"date_detection": false
}
}
然後在插入文檔:
POST /myindex/_doc
{
"content": "1985-12-24",
"postDate": "2009-11-15T14:12:12"
}
再查看映射結果爲:
{
"myindex" : {
"mappings" : {
"date_detection" : false,
"properties" : {
"content" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"postDate" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
現在兩個字段內容都包括日期,但都被映射爲text類型,並且有子類型keyword。但postDate也被映射爲字符串,失去了日期類型的能力。
我們現在顯示指定映射日期類型;
PUT /myindex
{
"mappings": {
"date_detection": false,
"properties": {
"postDate": {
"type": "date"
}
}
}
}
如果我們再次插入上面問題json內容,映射類型與我們期望的一致。但這種方法不靈活,尤其當有很多字段且有些字段之前並不能確定其類型時。
3. 使用命名規範映射日期字段
另外一種方法禁用日期推斷同時顯示映射特定字段作爲日期類型:
PUT /myindex
{
"mappings": {
"date_detection": false,
"dynamic_templates": [
{
"dates": {
"match": ".*Date|date",
"match_pattern": "regex",
"mapping": {
"type": "date"
}
}
}
]
}
}
比較兩者方法有差異。和前面一樣也禁用日期推斷,但之後不再提供屬性映射,而是提供提供基於名稱dates
動態映射。在名稱動態映射中指定正則表達式,符合表達式規範則使用日期類型。
使用這種方法,所有字符串不再會被映射爲日期類型,除了其名稱以Date結尾,如postDate,updateDate等。
這樣雖好,但不能把以Date結尾字段的值設置非日期字符串。但不能否認這種方法還是相對比較靈活,在實際應用中比較可行,畢竟對字段明確一些命名規範也屬於數據庫設計的一部分。
4. 總結
本文介紹了Elasticsearch的動態映射,並通過如何準確推斷日期類型示例進行說明,其他類型也可以使用類似方法。