Skip to content

Commit a684ef9

Browse files
authored
Optimized date parsing for numbers (#132462)
1 parent 54d3fd5 commit a684ef9

File tree

1 file changed

+35
-3
lines changed

1 file changed

+35
-3
lines changed

server/src/main/java/org/elasticsearch/index/mapper/DateFieldMapper.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
import java.util.Map;
7878
import java.util.Objects;
7979
import java.util.Set;
80+
import java.util.concurrent.TimeUnit;
8081
import java.util.function.BiFunction;
8182
import java.util.function.Function;
8283
import java.util.function.LongSupplier;
@@ -116,6 +117,11 @@ public long convert(TimeValue timeValue) {
116117
return timeValue.millis();
117118
}
118119

120+
@Override
121+
public long convert(long epochMillis) {
122+
return epochMillis;
123+
}
124+
119125
@Override
120126
public Instant toInstant(long value) {
121127
return Instant.ofEpochMilli(value);
@@ -147,6 +153,11 @@ public long convert(TimeValue timeValue) {
147153
return timeValue.nanos();
148154
}
149155

156+
@Override
157+
public long convert(long epochMillis) {
158+
return TimeUnit.MILLISECONDS.toNanos(epochMillis);
159+
}
160+
150161
@Override
151162
public Instant toInstant(long value) {
152163
return DateUtils.toInstant(value);
@@ -210,6 +221,11 @@ ToScriptFieldFactory<SortedNumericDocValues> getDefaultToScriptFieldFactory() {
210221
*/
211222
public abstract long convert(TimeValue timeValue);
212223

224+
/**
225+
* Convert an epoch millis timestamp into a long value in this resolution.
226+
*/
227+
public abstract long convert(long epochMillis);
228+
213229
/**
214230
* Decode the points representation of this field as milliseconds.
215231
*/
@@ -1234,17 +1250,18 @@ protected String contentType() {
12341250

12351251
@Override
12361252
protected void parseCreateField(DocumentParserContext context) throws IOException {
1237-
String dateAsString = context.parser().textOrNull();
12381253

12391254
long timestamp;
1240-
if (dateAsString == null) {
1255+
if (context.parser().currentToken() == XContentParser.Token.VALUE_NULL) {
12411256
if (nullValue == null) {
12421257
return;
12431258
}
12441259
timestamp = nullValue;
1260+
} else if (isEpochMillis(context)) {
1261+
timestamp = resolution.convert(context.parser().longValue());
12451262
} else {
12461263
try {
1247-
timestamp = fieldType().parse(dateAsString);
1264+
timestamp = fieldType().parse(context.parser().text());
12481265
} catch (IllegalArgumentException | ElasticsearchParseException | DateTimeException | ArithmeticException e) {
12491266
if (ignoreMalformed) {
12501267
context.addIgnoredField(mappedFieldType.name());
@@ -1262,6 +1279,21 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
12621279
indexValue(context, timestamp);
12631280
}
12641281

1282+
/*
1283+
If the value is a long and the date formater parses epoch millis, we can index the value directly.
1284+
This avoids the overhead of converting the long to a string and then parsing it back to a long via a date formatter.
1285+
Note that checking for the date formatter containing "epoch_millis" is not sufficient,
1286+
as there may be other formats compatible with a long value before "epoch_millis" (e.g., "epoch_second||epoch_millis").
1287+
*/
1288+
private boolean isEpochMillis(DocumentParserContext context) throws IOException {
1289+
DateFormatter dateFormatter = fieldType().dateTimeFormatter();
1290+
return context.parser().currentToken() == XContentParser.Token.VALUE_NUMBER
1291+
&& context.parser().numberType() == XContentParser.NumberType.LONG
1292+
&& (dateFormatter.equals(DEFAULT_DATE_TIME_FORMATTER)
1293+
|| dateFormatter.equals(DEFAULT_DATE_TIME_NANOS_FORMATTER)
1294+
|| dateFormatter.equals(EPOCH_MILLIS_PARSER));
1295+
}
1296+
12651297
private void indexValue(DocumentParserContext context, long timestamp) {
12661298
// DataStreamTimestampFieldMapper and TsidExtractingFieldMapper need to use timestamp value,
12671299
// so when this is true we store it in a well-known place

0 commit comments

Comments
 (0)