Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a consistent way to parse dates #61105

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions x-pack/plugin/runtime-fields/qa/rest/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ yamlRestTest {
'search/140_pre_filter_search_shards/pre_filter_shard_size with shards that have no hit', // Broken. Gotta fix.
'field_caps/30_filter/Field caps with index filter', // We don't support filtering field caps on runtime fields. What should we do?
'search.aggregation/10_histogram/*', // runtime_script doesn't support sub-fields. Maybe it should?
'search/250_distance_feature/test distance_feature query on date type', // This needs #60851
/////// TO FIX ///////

/////// NOT SUPPORTED ///////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.carrotsearch.randomizedtesting.annotations.Name;
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;

import org.elasticsearch.index.mapper.DateFieldMapper;
import org.elasticsearch.index.mapper.IpFieldMapper;
import org.elasticsearch.index.mapper.KeywordFieldMapper;
import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType;
Expand Down Expand Up @@ -160,7 +161,7 @@ private static String painlessToLoadFromSource(String name, String type) {
}

private static final Map<String, String> PAINLESS_TO_EMIT = Map.ofEntries(
// TODO implement dates against the parser
Map.entry(DateFieldMapper.CONTENT_TYPE, "millis(parse(value.toString()));"),
Map.entry(
NumberType.DOUBLE.typeName(),
"value(value instanceof Number ? ((Number) value).doubleValue() : Double.parseDouble(value.toString()));"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package org.elasticsearch.xpack.runtimefields;

import org.apache.lucene.index.LeafReaderContext;
import org.elasticsearch.common.time.DateFormatter;
import org.elasticsearch.painless.spi.Whitelist;
import org.elasticsearch.painless.spi.WhitelistLoader;
import org.elasticsearch.script.ScriptContext;
Expand All @@ -29,15 +30,18 @@ static List<Whitelist> whitelist() {
public static final String[] PARAMETERS = {};

public interface Factory extends ScriptFactory {
LeafFactory newFactory(Map<String, Object> params, SearchLookup searchLookup);
LeafFactory newFactory(Map<String, Object> params, SearchLookup searchLookup, DateFormatter formatter);
}

public interface LeafFactory {
DateScriptFieldScript newInstance(LeafReaderContext ctx) throws IOException;
}

public DateScriptFieldScript(Map<String, Object> params, SearchLookup searchLookup, LeafReaderContext ctx) {
private final DateFormatter formatter;

public DateScriptFieldScript(Map<String, Object> params, SearchLookup searchLookup, DateFormatter formatter, LeafReaderContext ctx) {
super(params, searchLookup, ctx);
this.formatter = formatter;
}

public static class Millis {
Expand Down Expand Up @@ -67,4 +71,15 @@ public void date(TemporalAccessor v) {
}
}

public static class Parse {
private final DateScriptFieldScript script;

public Parse(DateScriptFieldScript script) {
this.script = script;
}

public long parse(Object str) {
return script.formatter.parseMillis(str.toString());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public ScriptDateFieldData.Builder fielddataBuilder(String fullyQualifiedIndexNa
}

private DateScriptFieldScript.LeafFactory leafFactory(SearchLookup lookup) {
return scriptFactory.newFactory(script.getParams(), lookup);
return scriptFactory.newFactory(script.getParams(), lookup, dateTimeFormatter);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class org.elasticsearch.xpack.runtimefields.DateScriptFieldScript @no_import {
static_import {
void millis(org.elasticsearch.xpack.runtimefields.DateScriptFieldScript, long) bound_to org.elasticsearch.xpack.runtimefields.DateScriptFieldScript$Millis
void date(org.elasticsearch.xpack.runtimefields.DateScriptFieldScript, TemporalAccessor) bound_to org.elasticsearch.xpack.runtimefields.DateScriptFieldScript$Date
long parse(org.elasticsearch.xpack.runtimefields.DateScriptFieldScript, def) bound_to org.elasticsearch.xpack.runtimefields.DateScriptFieldScript$Parse
}

# This import is required to make painless happy and it isn't 100% clear why
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,12 @@ public <FactoryType> FactoryType compile(

private Object dummyScriptFactory(ScriptContext<?> context) {
if (context == DateScriptFieldScript.CONTEXT) {
return (DateScriptFieldScript.Factory) (params, lookup) -> ctx -> new DateScriptFieldScript(params, lookup, ctx) {
return (DateScriptFieldScript.Factory) (params, lookup, formatter) -> ctx -> new DateScriptFieldScript(
params,
lookup,
formatter,
ctx
) {
@Override
public void execute() {
new DateScriptFieldScript.Millis(this).millis(1595431354874L);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ protected ScriptDateMappedFieldType simpleMappedFieldType() throws IOException {
}

private ScriptDateMappedFieldType coolFormattedFieldType() throws IOException {
return build(simpleMappedFieldType().script, DateFormatter.forPattern("yyyy-MM-dd(-■_■)HH:mm:ss.SSSz"));
return build(simpleMappedFieldType().script, DateFormatter.forPattern("yyyy-MM-dd(-■_■)HH:mm:ss.SSSz||epoch_millis"));
}

@Override
Expand Down Expand Up @@ -405,16 +405,17 @@ public <FactoryType> FactoryType compile(
private DateScriptFieldScript.Factory factory(String code) {
switch (code) {
case "read_timestamp":
return (params, lookup) -> (ctx) -> new DateScriptFieldScript(params, lookup, ctx) {
return (params, lookup, formatter) -> ctx -> new DateScriptFieldScript(params, lookup, formatter, ctx) {
@Override
public void execute() {
for (Object timestamp : (List<?>) getSource().get("timestamp")) {
new DateScriptFieldScript.Millis(this).millis((Long) timestamp);
DateScriptFieldScript.Parse parse = new DateScriptFieldScript.Parse(this);
new DateScriptFieldScript.Millis(this).millis(parse.parse(timestamp));
}
}
};
case "add_days":
return (params, lookup) -> (ctx) -> new DateScriptFieldScript(params, lookup, ctx) {
return (params, lookup, formatter) -> ctx -> new DateScriptFieldScript(params, lookup, formatter, ctx) {
@Override
public void execute() {
for (Object timestamp : (List<?>) getSource().get("timestamp")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ setup:
}
params:
days: 1
# Test fetching from _source
# Test fetching from _source and parsing
tomorrow_from_source:
type: runtime_script
runtime_type: date
script:
source: |
Instant instant = Instant.ofEpochMilli(source['timestamp']);
Instant instant = Instant.ofEpochMilli(parse(source['timestamp']));
ZonedDateTime dt = ZonedDateTime.ofInstant(instant, ZoneId.of("UTC"));
date(dt.plus(1, ChronoUnit.DAYS));
# Test returning millis
Expand Down Expand Up @@ -82,7 +82,7 @@ setup:
{"index":{}}
{"timestamp": 1516383694000, "temperature": 200, "voltage": 4.2, "node": "c"}
{"index":{}}
{"timestamp": 1516297294000, "temperature": 202, "voltage": 4.0, "node": "c"}
{"timestamp": "2018-01-18T17:41:34.000Z", "temperature": 202, "voltage": 4.0, "node": "c"}

---
"get mapping":
Expand Down