Skip to content

Commit f703951

Browse files
committed
Allow field mappers to retrieve fields from source. (#56928)
This PR adds new method `FieldMapper#lookupValues(SourceLookup)` that extracts and parses the source values. This lets us return values like numbers and dates in a consistent format, and also handle special data types like `constant_keyword`. The `lookupValues` method calls into `parseSourceValue`, which mappers can override to specify how values should be parsed.
1 parent 572cd12 commit f703951

File tree

57 files changed

+736
-81
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+736
-81
lines changed

modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/RankFeatureFieldMapper.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -185,11 +185,7 @@ protected void parseCreateField(ParseContext context) throws IOException {
185185
float value;
186186
if (context.externalValueSet()) {
187187
Object v = context.externalValue();
188-
if (v instanceof Number) {
189-
value = ((Number) v).floatValue();
190-
} else {
191-
value = Float.parseFloat(v.toString());
192-
}
188+
value = objectToFloat(v);
193189
} else if (context.parser().currentToken() == Token.VALUE_NULL) {
194190
// skip
195191
return;
@@ -209,6 +205,19 @@ protected void parseCreateField(ParseContext context) throws IOException {
209205
context.doc().addWithKey(name(), new FeatureField("_feature", name(), value));
210206
}
211207

208+
private Float objectToFloat(Object value) {
209+
if (value instanceof Number) {
210+
return ((Number) value).floatValue();
211+
} else {
212+
return Float.parseFloat(value.toString());
213+
}
214+
}
215+
216+
@Override
217+
protected Float parseSourceValue(Object value) {
218+
return objectToFloat(value);
219+
}
220+
212221
@Override
213222
protected String contentType() {
214223
return CONTENT_TYPE;

modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/RankFeaturesFieldMapper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
175175
throw new AssertionError("parse is implemented directly");
176176
}
177177

178+
@Override
179+
protected Object parseSourceValue(Object value) {
180+
return value;
181+
}
182+
178183
@Override
179184
protected String contentType() {
180185
return CONTENT_TYPE;

modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/ScaledFloatFieldMapper.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,13 @@ private static double objectToDouble(Object value) {
485485
return doubleValue;
486486
}
487487

488+
@Override
489+
protected Double parseSourceValue(Object value) {
490+
double doubleValue = objectToDouble(value);
491+
double scalingFactor = fieldType().getScalingFactor();
492+
return Math.round(doubleValue * scalingFactor) / scalingFactor;
493+
}
494+
488495
private static class ScaledFloatIndexFieldData extends IndexNumericFieldData {
489496

490497
private final IndexNumericFieldData scaledFieldData;

modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/SearchAsYouTypeFieldMapper.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,11 @@ protected void parseCreateField(ParseContext context) {
473473
throw new UnsupportedOperationException();
474474
}
475475

476+
@Override
477+
protected Object parseSourceValue(Object value) {
478+
throw new UnsupportedOperationException();
479+
}
480+
476481
@Override
477482
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
478483

@@ -510,6 +515,11 @@ protected void mergeOptions(FieldMapper other, List<String> conflicts) {
510515

511516
}
512517

518+
@Override
519+
protected Object parseSourceValue(Object value) {
520+
throw new UnsupportedOperationException();
521+
}
522+
513523
@Override
514524
protected String contentType() {
515525
return "shingle";
@@ -665,6 +675,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
665675
}
666676
}
667677

678+
@Override
679+
protected String parseSourceValue(Object value) {
680+
return value.toString();
681+
}
682+
668683
@Override
669684
protected String contentType() {
670685
return CONTENT_TYPE;

modules/mapper-extras/src/main/java/org/elasticsearch/index/mapper/TokenCountFieldMapper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
150150
context.doc().addAll(NumberFieldMapper.NumberType.INTEGER.createFields(fieldType().name(), tokenCount, indexed, docValued, stored));
151151
}
152152

153+
@Override
154+
protected String parseSourceValue(Object value) {
155+
return value.toString();
156+
}
157+
153158
/**
154159
* Count position increments in a token stream. Package private for testing.
155160
* @param analyzer analyzer to create token stream

modules/mapper-extras/src/test/java/org/elasticsearch/index/mapper/RankFeatureFieldMapperTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,12 @@
2323
import org.apache.lucene.analysis.tokenattributes.TermFrequencyAttribute;
2424
import org.apache.lucene.document.FeatureField;
2525
import org.apache.lucene.index.IndexableField;
26+
import org.elasticsearch.Version;
27+
import org.elasticsearch.cluster.metadata.IndexMetadata;
2628
import org.elasticsearch.common.Strings;
2729
import org.elasticsearch.common.bytes.BytesReference;
2830
import org.elasticsearch.common.compress.CompressedXContent;
31+
import org.elasticsearch.common.settings.Settings;
2932
import org.elasticsearch.common.xcontent.XContentFactory;
3033
import org.elasticsearch.common.xcontent.XContentType;
3134
import org.elasticsearch.index.IndexService;
@@ -180,4 +183,12 @@ public void testRejectMultiValuedFields() throws MapperParsingException, IOExcep
180183
e.getCause().getMessage());
181184
}
182185

186+
public void testParseSourceValue() {
187+
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
188+
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
189+
RankFeatureFieldMapper mapper = new RankFeatureFieldMapper.Builder("field").build(context);
190+
191+
assertEquals(3.14f, mapper.parseSourceValue(3.14), 0.0001);
192+
assertEquals(42.9f, mapper.parseSourceValue("42.9"), 0.0001);
193+
}
183194
}

modules/mapper-extras/src/test/java/org/elasticsearch/index/mapper/ScaledFloatFieldMapperTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@
2121

2222
import org.apache.lucene.index.DocValuesType;
2323
import org.apache.lucene.index.IndexableField;
24+
import org.elasticsearch.Version;
25+
import org.elasticsearch.cluster.metadata.IndexMetadata;
2426
import org.elasticsearch.common.Strings;
2527
import org.elasticsearch.common.bytes.BytesReference;
2628
import org.elasticsearch.common.compress.CompressedXContent;
29+
import org.elasticsearch.common.settings.Settings;
2730
import org.elasticsearch.common.xcontent.XContentFactory;
2831
import org.elasticsearch.common.xcontent.XContentType;
2932
import org.elasticsearch.index.IndexService;
@@ -392,4 +395,15 @@ public void testMeta() throws Exception {
392395
new CompressedXContent(mapping3), MergeReason.MAPPING_UPDATE);
393396
assertEquals(mapping3, mapper.mappingSource().toString());
394397
}
398+
399+
public void testParseSourceValue() {
400+
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
401+
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
402+
ScaledFloatFieldMapper mapper = new ScaledFloatFieldMapper.Builder("field")
403+
.scalingFactor(100)
404+
.build(context);
405+
406+
assertEquals(3.14, mapper.parseSourceValue(3.1415926), 0.00001);
407+
assertEquals(3.14, mapper.parseSourceValue("3.1415"), 0.00001);
408+
}
395409
}

modules/parent-join/src/main/java/org/elasticsearch/join/mapper/MetaJoinFieldMapper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
147147
throw new IllegalStateException("Should never be called");
148148
}
149149

150+
@Override
151+
protected Object parseSourceValue(Object value) {
152+
throw new UnsupportedOperationException("The " + typeName() + " field is not stored in _source.");
153+
}
154+
150155
@Override
151156
protected String contentType() {
152157
return CONTENT_TYPE;

modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentIdFieldMapper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
191191
context.doc().add(new SortedDocValuesField(fieldType().name(), binaryValue));
192192
}
193193

194+
@Override
195+
protected Object parseSourceValue(Object value) {
196+
throw new UnsupportedOperationException("The " + typeName() + " field is not stored in _source.");
197+
}
198+
194199
@Override
195200
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
196201
ParentIdFieldMapper parentMergeWith = (ParentIdFieldMapper) other;

modules/parent-join/src/main/java/org/elasticsearch/join/mapper/ParentJoinFieldMapper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
361361
throw new UnsupportedOperationException("parsing is implemented in parse(), this method should NEVER be called");
362362
}
363363

364+
@Override
365+
protected Object parseSourceValue(Object value) {
366+
return value;
367+
}
368+
364369
@Override
365370
public void parse(ParseContext context) throws IOException {
366371
context.path().add(simpleName());

0 commit comments

Comments
 (0)