Skip to content

Commit d727f40

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 2e78f18 commit d727f40

File tree

57 files changed

+745
-89
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

+745
-89
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
@@ -164,11 +164,7 @@ protected void parseCreateField(ParseContext context) throws IOException {
164164
float value;
165165
if (context.externalValueSet()) {
166166
Object v = context.externalValue();
167-
if (v instanceof Number) {
168-
value = ((Number) v).floatValue();
169-
} else {
170-
value = Float.parseFloat(v.toString());
171-
}
167+
value = objectToFloat(v);
172168
} else if (context.parser().currentToken() == Token.VALUE_NULL) {
173169
// skip
174170
return;
@@ -188,6 +184,19 @@ protected void parseCreateField(ParseContext context) throws IOException {
188184
context.doc().addWithKey(name(), new FeatureField("_feature", name(), value));
189185
}
190186

187+
private Float objectToFloat(Object value) {
188+
if (value instanceof Number) {
189+
return ((Number) value).floatValue();
190+
} else {
191+
return Float.parseFloat(value.toString());
192+
}
193+
}
194+
195+
@Override
196+
protected Float parseSourceValue(Object value) {
197+
return objectToFloat(value);
198+
}
199+
191200
@Override
192201
protected String contentType() {
193202
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
@@ -169,6 +169,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
169169
throw new AssertionError("parse is implemented directly");
170170
}
171171

172+
@Override
173+
protected Object parseSourceValue(Object value) {
174+
return value;
175+
}
176+
172177
@Override
173178
protected boolean indexedByDefault() {
174179
return false;

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
@@ -494,6 +494,13 @@ private static double objectToDouble(Object value) {
494494
return doubleValue;
495495
}
496496

497+
@Override
498+
protected Double parseSourceValue(Object value) {
499+
double doubleValue = objectToDouble(value);
500+
double scalingFactor = fieldType().getScalingFactor();
501+
return Math.round(doubleValue * scalingFactor) / scalingFactor;
502+
}
503+
497504
private static class ScaledFloatIndexFieldData extends IndexNumericFieldData {
498505

499506
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
@@ -488,6 +488,11 @@ protected void parseCreateField(ParseContext context) {
488488
throw new UnsupportedOperationException();
489489
}
490490

491+
@Override
492+
protected Object parseSourceValue(Object value) {
493+
throw new UnsupportedOperationException();
494+
}
495+
491496
@Override
492497
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
493498

@@ -529,6 +534,11 @@ protected void mergeOptions(FieldMapper other, List<String> conflicts) {
529534

530535
}
531536

537+
@Override
538+
protected Object parseSourceValue(Object value) {
539+
throw new UnsupportedOperationException();
540+
}
541+
532542
@Override
533543
protected String contentType() {
534544
return "shingle";
@@ -687,6 +697,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
687697
}
688698
}
689699

700+
@Override
701+
protected String parseSourceValue(Object value) {
702+
return value.toString();
703+
}
704+
690705
@Override
691706
protected String contentType() {
692707
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
@@ -159,6 +159,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
159159
context.doc().addAll(NumberFieldMapper.NumberType.INTEGER.createFields(fieldType().name(), tokenCount, indexed, docValued, stored));
160160
}
161161

162+
@Override
163+
protected String parseSourceValue(Object value) {
164+
return value.toString();
165+
}
166+
162167
/**
163168
* Count position increments in a token stream. Package private for testing.
164169
* @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;
@@ -186,4 +189,12 @@ public void testRejectMultiValuedFields() throws MapperParsingException, IOExcep
186189
e.getCause().getMessage());
187190
}
188191

192+
public void testParseSourceValue() {
193+
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
194+
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
195+
RankFeatureFieldMapper mapper = new RankFeatureFieldMapper.Builder("field").build(context);
196+
197+
assertEquals(3.14f, mapper.parseSourceValue(3.14), 0.0001);
198+
assertEquals(42.9f, mapper.parseSourceValue("42.9"), 0.0001);
199+
}
189200
}

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;
@@ -398,4 +401,15 @@ public void testMeta() throws Exception {
398401
new CompressedXContent(mapping3), MergeReason.MAPPING_UPDATE);
399402
assertEquals(mapping3, mapper.mappingSource().toString());
400403
}
404+
405+
public void testParseSourceValue() {
406+
Settings settings = Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
407+
Mapper.BuilderContext context = new Mapper.BuilderContext(settings, new ContentPath());
408+
ScaledFloatFieldMapper mapper = new ScaledFloatFieldMapper.Builder("field")
409+
.scalingFactor(100)
410+
.build(context);
411+
412+
assertEquals(3.14, mapper.parseSourceValue(3.1415926), 0.00001);
413+
assertEquals(3.14, mapper.parseSourceValue("3.1415"), 0.00001);
414+
}
401415
}

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
@@ -144,6 +144,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
144144
throw new IllegalStateException("Should never be called");
145145
}
146146

147+
@Override
148+
protected Object parseSourceValue(Object value) {
149+
throw new UnsupportedOperationException("The " + typeName() + " field is not stored in _source.");
150+
}
151+
147152
@Override
148153
protected String contentType() {
149154
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
@@ -195,6 +195,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
195195
context.doc().add(new SortedDocValuesField(fieldType().name(), binaryValue));
196196
}
197197

198+
@Override
199+
protected Object parseSourceValue(Object value) {
200+
throw new UnsupportedOperationException("The " + typeName() + " field is not stored in _source.");
201+
}
202+
198203
@Override
199204
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
200205
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
@@ -357,6 +357,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
357357
throw new UnsupportedOperationException("parsing is implemented in parse(), this method should NEVER be called");
358358
}
359359

360+
@Override
361+
protected Object parseSourceValue(Object value) {
362+
return value;
363+
}
364+
360365
@Override
361366
public void parse(ParseContext context) throws IOException {
362367
context.path().add(simpleName());

0 commit comments

Comments
 (0)