Skip to main content
 首页 » 编程设计

Elasticsearch动态映射与日期类型

2022年07月19日136lvdongjie

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的动态映射,并通过如何准确推断日期类型示例进行说明,其他类型也可以使用类似方法。


本文参考链接:https://blog.csdn.net/neweastsun/article/details/105324174
阅读延展