Mappings: Bring back numeric_resolution.

We had an undocumented parameter called `numeric_resolution` which allows to
configure how to deal with dates when provided as a number. The default is to
handle them as milliseconds, but you can also opt-on for eg. seconds.

Close #10072
This commit is contained in:
Adrien Grand 2015-04-03 19:54:14 +02:00
parent 3f8908acfb
commit c7115f8364
3 changed files with 44 additions and 5 deletions

View File

@ -378,6 +378,9 @@ defaults to `true` or to the parent `object` type setting.
|`ignore_malformed` |Ignored a malformed number. Defaults to `false`. |`ignore_malformed` |Ignored a malformed number. Defaults to `false`.
|`numeric_resolution` |The unit to use when passed in a numeric values. Possible
values include `seconds` and `milliseconds` (default).
|======================================================================= |=======================================================================
[float] [float]

View File

@ -488,13 +488,14 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
} }
if (value != null) { if (value != null) {
final long timestamp = timeUnit.toMillis(value);
if (fieldType.indexOptions() != IndexOptions.NONE || fieldType.stored()) { if (fieldType.indexOptions() != IndexOptions.NONE || fieldType.stored()) {
CustomLongNumericField field = new CustomLongNumericField(this, value, fieldType); CustomLongNumericField field = new CustomLongNumericField(this, timestamp, fieldType);
field.setBoost(boost); field.setBoost(boost);
fields.add(field); fields.add(field);
} }
if (hasDocValues()) { if (hasDocValues()) {
addDocValue(context, fields, value); addDocValue(context, fields, timestamp);
} }
} }
} }
@ -553,8 +554,7 @@ public class DateFieldMapper extends NumberFieldMapper<Long> {
return dateTimeFormatter.parser().parseMillis(value); return dateTimeFormatter.parser().parseMillis(value);
} catch (RuntimeException e) { } catch (RuntimeException e) {
try { try {
long time = Long.parseLong(value); return Long.parseLong(value);
return timeUnit.toMillis(time);
} catch (NumberFormatException e1) { } catch (NumberFormatException e1) {
throw new MapperParsingException("failed to parse date field [" + value + "], tried both date format [" + dateTimeFormatter.format() + "], and timestamp number with locale [" + dateTimeFormatter.locale() + "]", e); throw new MapperParsingException("failed to parse date field [" + value + "], tried both date format [" + dateTimeFormatter.format() + "], and timestamp number with locale [" + dateTimeFormatter.locale() + "]", e);
} }

View File

@ -22,6 +22,7 @@ package org.elasticsearch.index.mapper.date;
import org.apache.lucene.analysis.NumericTokenStream.NumericTermAttribute; import org.apache.lucene.analysis.NumericTokenStream.NumericTermAttribute;
import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.index.DocValuesType; import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.search.Filter; import org.apache.lucene.search.Filter;
import org.apache.lucene.search.NumericRangeFilter; import org.apache.lucene.search.NumericRangeFilter;
import org.elasticsearch.ElasticsearchIllegalArgumentException; import org.elasticsearch.ElasticsearchIllegalArgumentException;
@ -38,10 +39,12 @@ import org.elasticsearch.index.mapper.DocumentMapperParser;
import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.ParseContext.Document;
import org.elasticsearch.index.mapper.ParsedDocument; import org.elasticsearch.index.mapper.ParsedDocument;
import org.elasticsearch.index.mapper.core.DateFieldMapper; import org.elasticsearch.index.mapper.core.DateFieldMapper;
import org.elasticsearch.index.mapper.core.LongFieldMapper; import org.elasticsearch.index.mapper.core.LongFieldMapper;
import org.elasticsearch.index.mapper.core.StringFieldMapper; import org.elasticsearch.index.mapper.core.StringFieldMapper;
import org.elasticsearch.search.aggregations.support.ValuesSource.Numeric;
import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.test.ElasticsearchSingleNodeTest; import org.elasticsearch.test.ElasticsearchSingleNodeTest;
import org.elasticsearch.test.TestSearchContext; import org.elasticsearch.test.TestSearchContext;
@ -55,8 +58,8 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import static org.elasticsearch.index.mapper.string.SimpleStringMappingTests.docValuesType;
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder; import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
import static org.elasticsearch.index.mapper.string.SimpleStringMappingTests.docValuesType;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.instanceOf;
@ -396,4 +399,37 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
assertThat(dateFieldMapperMap.get("field"), is(instanceOf(Map.class))); assertThat(dateFieldMapperMap.get("field"), is(instanceOf(Map.class)));
return (Map<String, String>) dateFieldMapperMap.get("field"); return (Map<String, String>) dateFieldMapperMap.get("field");
} }
private static long getDateAsMillis(Document doc, String field) {
for (IndexableField f : doc.getFields(field)) {
if (f.numericValue() != null) {
return f.numericValue().longValue();
}
}
throw new AssertionError("missing");
}
public void testNumericResolution() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("date_field").field("type", "date").field("format", "date_time").field("numeric_resolution", "seconds").endObject().endObject()
.endObject().endObject().string();
DocumentMapper defaultMapper = mapper(mapping);
// provided as an int
ParsedDocument doc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("date_field", 42)
.endObject()
.bytes());
assertThat(getDateAsMillis(doc.rootDoc(), "date_field"), equalTo(42000L));
// provided as a string
doc = defaultMapper.parse("type", "2", XContentFactory.jsonBuilder()
.startObject()
.field("date_field", "43")
.endObject()
.bytes());
assertThat(getDateAsMillis(doc.rootDoc(), "date_field"), equalTo(43000L));
}
} }