国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Elasticsearch Date類型,時間存儲相關說明

2019-11-08 03:12:29
字體:
來源:轉載
供稿:網友

從昨晚開始,到今天中午之前,一直在糾結時間存儲問題,昨晚是糾結時間取出來的問題。

其實我的想法很簡單,我就想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  。

好了上面觀點純屬個人觀點。可能存在錯誤和參雜個人色彩。請勿作為直接參考。錯誤的地方,請在下面留言。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 湖北省| 碌曲县| 孝感市| 太和县| 旺苍县| 泗洪县| 怀柔区| 临沭县| 柘荣县| 峨边| 聊城市| 平阴县| 丰城市| 开封市| 浏阳市| 台南县| 绥宁县| 周口市| 枝江市| 齐齐哈尔市| 桐城市| 晋城| 古蔺县| 神农架林区| 平度市| 万州区| 邢台县| 太康县| 石首市| 永定县| 重庆市| 新泰市| 临夏县| 米林县| 余江县| 托克托县| 贞丰县| 大田县| 文昌市| 旺苍县| 惠来县|