Skip to content

Commit adcc7c0

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 7af042b commit adcc7c0

File tree

57 files changed

+737
-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

+737
-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
@@ -162,11 +162,7 @@ protected void parseCreateField(ParseContext context) throws IOException {
162162
float value;
163163
if (context.externalValueSet()) {
164164
Object v = context.externalValue();
165-
if (v instanceof Number) {
166-
value = ((Number) v).floatValue();
167-
} else {
168-
value = Float.parseFloat(v.toString());
169-
}
165+
value = objectToFloat(v);
170166
} else if (context.parser().currentToken() == Token.VALUE_NULL) {
171167
// skip
172168
return;
@@ -186,6 +182,19 @@ protected void parseCreateField(ParseContext context) throws IOException {
186182
context.doc().addWithKey(name(), new FeatureField("_feature", name(), value));
187183
}
188184

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

171+
@Override
172+
protected Object parseSourceValue(Object value) {
173+
return value;
174+
}
175+
171176
@Override
172177
protected boolean indexedByDefault() {
173178
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
@@ -496,6 +496,13 @@ private static double objectToDouble(Object value) {
496496
return doubleValue;
497497
}
498498

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

501508
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
@@ -491,6 +491,11 @@ protected void parseCreateField(ParseContext context) {
491491
throw new UnsupportedOperationException();
492492
}
493493

494+
@Override
495+
protected Object parseSourceValue(Object value) {
496+
throw new UnsupportedOperationException();
497+
}
498+
494499
@Override
495500
protected void mergeOptions(FieldMapper other, List<String> conflicts) {
496501

@@ -532,6 +537,11 @@ protected void mergeOptions(FieldMapper other, List<String> conflicts) {
532537

533538
}
534539

540+
@Override
541+
protected Object parseSourceValue(Object value) {
542+
throw new UnsupportedOperationException();
543+
}
544+
535545
@Override
536546
protected String contentType() {
537547
return "shingle";
@@ -684,6 +694,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
684694
}
685695
}
686696

697+
@Override
698+
protected String parseSourceValue(Object value) {
699+
return value.toString();
700+
}
701+
687702
@Override
688703
protected String contentType() {
689704
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
@@ -158,6 +158,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
158158
context.doc().addAll(NumberFieldMapper.NumberType.INTEGER.createFields(fieldType().name(), tokenCount, indexed, docValued, stored));
159159
}
160160

161+
@Override
162+
protected String parseSourceValue(Object value) {
163+
return value.toString();
164+
}
165+
161166
/**
162167
* Count position increments in a token stream. Package private for testing.
163168
* @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
@@ -194,6 +194,11 @@ protected void parseCreateField(ParseContext context) throws IOException {
194194
context.doc().add(new SortedDocValuesField(fieldType().name(), binaryValue));
195195
}
196196

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

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

0 commit comments

Comments
 (0)