Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.LongSupplier;
Expand Down Expand Up @@ -116,6 +117,11 @@ public long convert(TimeValue timeValue) {
return timeValue.millis();
}

@Override
public long convert(long epochMillis) {
return epochMillis;
}

@Override
public Instant toInstant(long value) {
return Instant.ofEpochMilli(value);
Expand Down Expand Up @@ -147,6 +153,11 @@ public long convert(TimeValue timeValue) {
return timeValue.nanos();
}

@Override
public long convert(long epochMillis) {
return TimeUnit.MILLISECONDS.toNanos(epochMillis);
}

@Override
public Instant toInstant(long value) {
return DateUtils.toInstant(value);
Expand Down Expand Up @@ -210,6 +221,11 @@ ToScriptFieldFactory<SortedNumericDocValues> getDefaultToScriptFieldFactory() {
*/
public abstract long convert(TimeValue timeValue);

/**
* Convert an epoch millis timestamp into a long value in this resolution.
*/
public abstract long convert(long epochMillis);

/**
* Decode the points representation of this field as milliseconds.
*/
Expand Down Expand Up @@ -1234,17 +1250,18 @@ protected String contentType() {

@Override
protected void parseCreateField(DocumentParserContext context) throws IOException {
String dateAsString = context.parser().textOrNull();

long timestamp;
if (dateAsString == null) {
if (context.parser().currentToken() == XContentParser.Token.VALUE_NULL) {
if (nullValue == null) {
return;
}
timestamp = nullValue;
} else if (isEpochMillis(context)) {
timestamp = resolution.convert(context.parser().longValue());
} else {
try {
timestamp = fieldType().parse(dateAsString);
timestamp = fieldType().parse(context.parser().text());
} catch (IllegalArgumentException | ElasticsearchParseException | DateTimeException | ArithmeticException e) {
if (ignoreMalformed) {
context.addIgnoredField(mappedFieldType.name());
Expand All @@ -1262,6 +1279,21 @@ protected void parseCreateField(DocumentParserContext context) throws IOExceptio
indexValue(context, timestamp);
}

/*
If the value is a long and the date formater parses epoch millis, we can index the value directly.
This avoids the overhead of converting the long to a string and then parsing it back to a long via a date formatter.
Note that checking for the date formatter containing "epoch_millis" is not sufficient,
as there may be other formats compatible with a long value before "epoch_millis" (e.g., "epoch_second||epoch_millis").
*/
private boolean isEpochMillis(DocumentParserContext context) throws IOException {
DateFormatter dateFormatter = fieldType().dateTimeFormatter();
return context.parser().currentToken() == XContentParser.Token.VALUE_NUMBER
&& context.parser().numberType() == XContentParser.NumberType.LONG
&& (dateFormatter.equals(DEFAULT_DATE_TIME_FORMATTER)
|| dateFormatter.equals(DEFAULT_DATE_TIME_NANOS_FORMATTER)
|| dateFormatter.equals(EPOCH_MILLIS_PARSER));
}

private void indexValue(DocumentParserContext context, long timestamp) {
// DataStreamTimestampFieldMapper and TsidExtractingFieldMapper need to use timestamp value,
// so when this is true we store it in a well-known place
Expand Down