Elasticsearch Date类型,时间存储相关说明
从昨晚开始,到今天中午之前,一直在纠结时间存储问题,昨晚是纠结时间取出来的问题。
其实我的想法很简单,我就想java.util.Date
存储到 Elasticsearch ,然后从 Elasticsearch 中再取出来的时候,它是个Date
,不需要我任何转换。
但是发现好像不行。
我开始在创建 Mapping 的时候,就是为:
//...省略部分代码
.startObject("create_date").field("type","date").field("format","yyyy-MM-dd HH:mm:ss").endObject()
//...省略部分代码
指定了Type
为Date
,并且format
为yyyy-MM-dd HH:mm:ss
,然后new Date();
插入后报错:
message [MapperParsingException[failed to parse [create_date]]; nested: IllegalArgumentException[Invalid format: "2016-07-04T03:03:12.616Z" is malformed at "T03:03:12.616Z"];]
根据错误提示,我先把时间格式化,然后插入:
result.put("create_date", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(create_date));
然后插入OK。后来我看了源码,才恍然大悟。新版本(我不知道从什么版本开始,我以前最开始用的是0.9)值是根据value 的类型来判断。我贴一下。
org.elasticsearch.common.xcontent.XContentBuilder
中 1248
行。
private void writeValue(Object value) throws IOException {
if (value == null) {
generator.writeNull();
return;
}
Class<?> type = value.getClass();
if (type == String.class) {
generator.writeString((String) value);
} else if (type == Integer.class) {
generator.writeNumber(((Integer) value).intValue());
} else if (type == Long.class) {
generator.writeNumber(((Long) value).longValue());
} else if (type == Float.class) {
generator.writeNumber(((Float) value).floatValue());
} else if (type == Double.class) {
generator.writeNumber(((Double) value).doubleValue());
} else if (type == Byte.class) {
generator.writeNumber(((Byte)value).byteValue());
} else if (type == Short.class) {
generator.writeNumber(((Short) value).shortValue());
} else if (type == Boolean.class) {
generator.writeBoolean(((Boolean) value).booleanValue());
} else if (type == GeoPoint.class) {
generator.writeStartObject();
generator.writeNumberField("lat", ((GeoPoint) value).lat());
generator.writeNumberField("lon", ((GeoPoint) value).lon());
generator.writeEndObject();
} else if (value instanceof Map) {
writeMap((Map) value);
} else if (value instanceof Path) {
//Path implements Iterable<Path> and causes endless recursion and a StackOverFlow if treated as an Iterable here
generator.writeString(value.toString());
} else if (value instanceof Iterable) {
generator.writeStartArray();
for (Object v : (Iterable<?>) value) {
writeValue(v);
}
generator.writeEndArray();
} else if (value instanceof Object[]) {
generator.writeStartArray();
for (Object v : (Object[]) value) {
writeValue(v);
}
generator.writeEndArray();
} else if (type == byte[].class) {
generator.writeBinary((byte[]) value);
/* 注意这里:如果是Date类型,就是以字符串输出。
如果你跟进去看。代码在下个片段。
*/
} else if (value instanceof Date) {
generator.writeString(XContentBuilder.defaultDatePrinter.print(((Date) value).getTime()));
} else if (value instanceof Calendar) {
generator.writeString(XContentBuilder.defaultDatePrinter.print((((Calendar) value)).getTimeInMillis()));
} else if (value instanceof ReadableInstant) {
generator.writeString(XContentBuilder.defaultDatePrinter.print((((ReadableInstant) value)).getMillis()));
} else if (value instanceof BytesReference) {
BytesReference bytes = (BytesReference) value;
if (!bytes.hasArray()) {
bytes = bytes.toBytesArray();
}
generator.writeBinary(bytes.array(), bytes.arrayOffset(), bytes.length());
} else if (value instanceof BytesRef) {
BytesRef bytes = (BytesRef) value;
generator.writeBinary(bytes.bytes, bytes.offset, bytes.length);
} else if (value instanceof Text) {
Text text = (Text) value;
if (text.hasBytes() && text.bytes().hasArray()) {
generator.writeUTF8String(text.bytes().array(), text.bytes().arrayOffset(), text.bytes().length());
} else if (text.hasString()) {
generator.writeString(text.string());
} else {
BytesArray bytesArray = text.bytes().toBytesArray();
generator.writeUTF8String(bytesArray.array(), bytesArray.arrayOffset(), bytesArray.length());
}
} else if (value instanceof ToXContent) {
((ToXContent) value).toXContent(this, ToXContent.EMPTY_PARAMS);
} else if (value instanceof double[]) {
generator.writeStartArray();
for (double v : (double[]) value) {
generator.writeNumber(v);
}
generator.writeEndArray();
} else if (value instanceof long[]) {
generator.writeStartArray();
for (long v : (long[]) value) {
generator.writeNumber(v);
}
generator.writeEndArray();
} else if (value instanceof int[]) {
generator.writeStartArray();
for (int v : (int[]) value) {
generator.writeNumber(v);
}
generator.writeEndArray();
} else if (value instanceof float[]) {
generator.writeStartArray();
for (float v : (float[]) value) {
generator.writeNumber(v);
}
generator.writeEndArray();
} else if (value instanceof short[]) {
generator.writeStartArray();
for (short v : (short[]) value) {
generator.writeNumber(v);
}
generator.writeEndArray();
} else {
// if this is a "value" object, like enum, DistanceUnit, ..., just toString it
// yea, it can be misleading when toString a Java class, but really, jackson should be used in that case
generator.writeString(value.toString());
//throw new ElasticsearchIllegalArgumentException("type not supported for generic value conversion: " + type);
}
}
我们看下这部分:XContentBuilder.defaultDatePrinter.print(((Date) value).getTime())
进去后。看到如下:
/**
* Prints a millisecond instant to a String.
* <p>
* This method will use the override zone and the override chronology if
* they are set. Otherwise it will use the ISO chronology and default zone.
*
* @param instant millis since 1970-01-01T00:00:00Z
* @return the printed result
*/
public String print(long instant) {
StringBuilder buf = new StringBuilder(requirePrinter().estimatePrintedLength());
try {
printTo((Appendable) buf, instant);
} catch (IOException ex) {
// StringBuilder does not throw IOException
}
return buf.toString();
}
看到这里就明白了吧。他最终的输出方式都是以字符串输出,只是默认的格式是:1970-01-01T00:00:00Z
,也就是默认的 UTC
格式。我的时间转换结果成:2016-07-04T03:03:12.616Z
这里并且有时区的概念,东八区,这里输出的时间少了8
个小时。这个得注意。
总结了下。最终输出都是String
类型。感觉不友好。我本想的是,我不管存入是怎么样,我取出来得是Date
对象就可以了。
官网时间(Date)格式说明
关于时间类型说明:https://www.elastic.co/guide/en/elasticsearch/reference/current/date.html
关于时间类型格式化:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#strict-date-time
JSON doesn’t have a date datatype, so dates in Elasticsearch can either be:
- strings containing formatted dates, e.g. "2015-01-01" or "2015/01/01 12:10:30".
- a long number representing milliseconds-since-the-epoch.
- an integer representing seconds-since-the-epoch.
Internally, dates are converted to UTC (if the time-zone is specified) and stored as a long number representing milliseconds-since-the-epoch.
Date formats can be customised, but if no format is specified then it uses the default:
"strict_date_optional_time||epoch_millis"
This means that it will accept dates with optional timestamps, which conform to the formats supported by strict_date_optional_time or milliseconds-since-the-epoch.
解决方法及问题:
1.时间输出格式,如果是默认 UTC 格式,时间不是我们常用的格式,而且时区问题,少了8个小时。
解决方案:
直接用毫秒值,缺点为不直观。
直接设置format为你想要的格式,比如
“yyyy-MM-dd HH:mm:ss” 然后存储的时候,指定格式,并且 Mapping 也是指定相同的format
。
2.存储Date,和取出来也是Dete?
解决方案:
- 存储的时候利用各种JSON对象,比如 json-lib , fastjson , Jackson , gson 等等。存储的时候就可以用JSON Format一下再存储,然后取出来后,在用
JSON.toBean(json,POJO.class)
,就解决了,这里利用的是相同 JSON 包转成 JSON ,然后又toBean
回来,是没问题的,然后 Elasticsearch 也支持存储 JSON 。
好了上面观点纯属个人观点。可能存在错误和参杂个人色彩。请勿作为直接参考。错误的地方,请在下面留言。
Elasticsearch Date类型,时间存储相关说明相关推荐
- java获取Date类型时间的前3个月,后3个月,前3天,后3天
java获取Date类型时间的前3个月,后3个月,前3天,后3天 Calendar cal = Calendar.getInstance(); Date date = new Date(); cal. ...
- @JsonFormat Date类型时间 格式化 注解 使用
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. @JsonFormat注解是一个时间格式化注解,比如我们存储在mysql中的数据是date类型的,当 ...
- feign date类型时间错误问题
问题 在feign传输date类型的数据时,在调用方时间正确,而被调用方获取时时间会相差14个小时. 原因 Feign客户端在进行通信时,会将Date类型对象转为String类型,如果这个时间是北京时 ...
- iBatis Date类型时间丢失问题
下面只是解决了时间插入的问题,至于从数据库读书时间的问题,还需要经进一步. 参照下面的帖子 : http://code.google.com/a/eclipselabs.org/p/demo1/wik ...
- Date类型时间格式注解
@ApiModelProperty(value = "生产日期") @DateTimeFormat(pattern = "yyyy-MM-dd") //后端-- ...
- 数据库里面date类型时间有时差,时区问题
SpringBoot项目,mysql数据库 数据库的时区 show variables like "%time_zone%"; 阿里云的数据库 根据网上的资料,可以更改数据库的sy ...
- 全球机房遇到的 Date类型 比较时间区间解决方案
日本机房展示: ************************日本机房**********************//查询当前时间对应的时区 mysql> show variables lik ...
- 数据库时间为datetime(date)类型,开发使用String类型的优劣
随笔: 在mysql数据库中,关于时间的使用是datetime类型,而在开发中使用string类型 datetime类型是规范的格式,储存空间8 bytes,YYYY-MM-DD HH:MM:SS格式 ...
- Oracle date(时间)类型详解
常用日期型数据类型 TIMESTAMP类型是DATE类型的一个扩展,DATE类型会存储年月日时分秒信息,TIMESTAMP类型精度更高,会存储到微秒.纳秒. 1.DATE 展示格式既可 ...
最新文章
- 美国《时代》周刊公布年度25大最佳发明名单
- H264格式具体说明
- C语言函数集(十七)
- hdu2722 简单最短路,处理好输入就行
- RIM发警告 部分黑莓手机存在安全漏洞
- ThreadLocal 中的ThreadLocalMap
- received packet with own address as source address
- 我们为何需要单点登录系统
- python 去除不可见字符\x00
- Qt文档阅读笔记-关于Q_DECLARE_METATYPE原理以及使用
- 【TensorFlow】TensorFlow从浅入深系列之一 -- 教你如何设置学习率(指数衰减法)
- String Algorithm
- Kaldi nnet3的fastlstm与标准LSTM
- [转]看懂 Serverless,这一篇就够了
- java 文件无法下载_无法从Java中的URL下载文件
- java poi 读取Excel中的手机号
- 如何测试5.1声卡测试软件,功能至上--德国坦克AUREON 5.1初步测试
- 开始学习机器学习之前你必须要了解的知识有哪些?机器学习系列入门篇
- 结巴分词,停用词生成词云图
- Dijkstra 路径规划算法原理详解及 Python 代码实现