Elasticsearch動態映射與日期類型

Elasticsearch動態映射與日期類型

JSon沒有日期類型,但Elasticsearch能自動爲我們映射日期字段。如果結合日期字段命名約定可以幫我我們準確實現動態映射。

1. 動態映射

Elasticsearch的動態映射特性可以實現根據字段值自動映射字段類型(缺省類型),因此無需顯示定義如何索引、存儲字段,Elasticsearch通過檢查JSon屬性的內容自動推斷類型。請看示例:

如果之前沒有索引myindex,Elasticsearch會幫助我們做下列工作:

POST /myindex/_doc
{
    "content": "Hello World!",
    "postDate": "2009-11-15T14:12:12"
}
  1. 創建索引myindex,包括兩個字段content和postDate
  2. 使用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的動態映射,並通過如何準確推斷日期類型示例進行說明,其他類型也可以使用類似方法。

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