Skip to content

Commit 37228d0

Browse files
authored
Remove last DocumentMapper reference from MappingLookup (#67157)
As part of #66295 we made QueryShardContext perform mapping lookups through MappingLookup rather than MapperService. That helps as MapperService relies on DocumentMapper which may change througout the execution of the search request. At search time, the percolate query also needs to parse documents, which made us add a parse method to MappingLookup.Such parse method currently relies on calling DocumentMapper#parseDocument through a function, but we would like to rather make this easier to follow. (see https://github.com/elastic/elasticsearch/pull/66295/files#r544639868) We recently removed the need to provide the entire DocumentMapper to DocumentParser#parse, opening the possibility for using DocumentParser directly when needing to parse a document at query time. This commit adds everything that is needed (namely Mapping, IndexSettings and IndexAnalyzers) to MappingLookup so that it can parse a document through DocumentParser without relying on DocumentMapper. As a bonus, given that MappingLookup holds a reference to these three additional objects, we can make DocumentMapper rely on MappingLookup to retrieve those and not hold its own same references to them. Along the same lines, given that MappingLookup holds all that's necessary to parse a document, the signature of DocumentParser#parse can be simplified by replacing most of its arguments with MappingLookup and retrieving what is needed from it.
1 parent 287719e commit 37228d0

File tree

20 files changed

+245
-307
lines changed

20 files changed

+245
-307
lines changed

modules/percolator/src/test/java/org/elasticsearch/percolator/CandidateQueryTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,8 +1119,8 @@ private void duelRun(PercolateQuery.QueryStore queryStore, MemoryIndex memoryInd
11191119
}
11201120

11211121
private void addQuery(Query query, List<ParseContext.Document> docs) {
1122-
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(documentMapper.mapping(),
1123-
documentMapper.mappers(), mapperService.getIndexSettings(), mapperService.getIndexAnalyzers(), null, null, null, null);
1122+
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(
1123+
documentMapper.mappers(), null, null, null, null);
11241124
fieldMapper.processQuery(query, parseContext);
11251125
ParseContext.Document queryDocument = parseContext.doc();
11261126
// Add to string representation of the query to make debugging easier:

modules/percolator/src/test/java/org/elasticsearch/percolator/PercolatorFieldMapperTests.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ public void testExtractTerms() throws Exception {
181181

182182
DocumentMapper documentMapper = mapperService.documentMapper("doc");
183183
PercolatorFieldMapper fieldMapper = (PercolatorFieldMapper) documentMapper.mappers().getMapper(fieldName);
184-
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(documentMapper.mapping(),
185-
documentMapper.mappers(), mapperService.getIndexSettings(), mapperService.getIndexAnalyzers(), null, null, null, null);
184+
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(documentMapper.mappers(),
185+
null, null, null, null);
186186
fieldMapper.processQuery(bq.build(), parseContext);
187187
ParseContext.Document document = parseContext.doc();
188188

@@ -203,8 +203,7 @@ public void testExtractTerms() throws Exception {
203203
bq.add(termQuery1, Occur.MUST);
204204
bq.add(termQuery2, Occur.MUST);
205205

206-
parseContext = new ParseContext.InternalParseContext(documentMapper.mapping(),
207-
documentMapper.mappers(), mapperService.getIndexSettings(), mapperService.getIndexAnalyzers(), null, null, null, null);
206+
parseContext = new ParseContext.InternalParseContext(documentMapper.mappers(), null, null, null, null);
208207
fieldMapper.processQuery(bq.build(), parseContext);
209208
document = parseContext.doc();
210209

@@ -233,8 +232,8 @@ public void testExtractRanges() throws Exception {
233232

234233
DocumentMapper documentMapper = mapperService.documentMapper("doc");
235234
PercolatorFieldMapper fieldMapper = (PercolatorFieldMapper) documentMapper.mappers().getMapper(fieldName);
236-
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(documentMapper.mapping(),
237-
documentMapper.mappers(), mapperService.getIndexSettings(), mapperService.getIndexAnalyzers(), null, null, null, null);
235+
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(
236+
documentMapper.mappers(), null, null, null, null);
238237
fieldMapper.processQuery(bq.build(), parseContext);
239238
ParseContext.Document document = parseContext.doc();
240239

@@ -259,8 +258,7 @@ public void testExtractRanges() throws Exception {
259258
.rangeQuery(15, 20, true, true, null, null, null, context);
260259
bq.add(rangeQuery2, Occur.MUST);
261260

262-
parseContext = new ParseContext.InternalParseContext(documentMapper.mapping(),
263-
documentMapper.mappers(), mapperService.getIndexSettings(), mapperService.getIndexAnalyzers(), null, null, null, null);
261+
parseContext = new ParseContext.InternalParseContext(documentMapper.mappers(), null, null, null, null);
264262
fieldMapper.processQuery(bq.build(), parseContext);
265263
document = parseContext.doc();
266264

@@ -283,8 +281,8 @@ public void testExtractTermsAndRanges_failed() throws Exception {
283281
TermRangeQuery query = new TermRangeQuery("field1", new BytesRef("a"), new BytesRef("z"), true, true);
284282
DocumentMapper documentMapper = mapperService.documentMapper("doc");
285283
PercolatorFieldMapper fieldMapper = (PercolatorFieldMapper) documentMapper.mappers().getMapper(fieldName);
286-
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(documentMapper.mapping(),
287-
documentMapper.mappers(), mapperService.getIndexSettings(), mapperService.getIndexAnalyzers(), null, null, null, null);
284+
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(documentMapper.mappers(),
285+
null, null, null, null);
288286
fieldMapper.processQuery(query, parseContext);
289287
ParseContext.Document document = parseContext.doc();
290288

@@ -298,8 +296,8 @@ public void testExtractTermsAndRanges_partial() throws Exception {
298296
PhraseQuery phraseQuery = new PhraseQuery("field", "term");
299297
DocumentMapper documentMapper = mapperService.documentMapper("doc");
300298
PercolatorFieldMapper fieldMapper = (PercolatorFieldMapper) documentMapper.mappers().getMapper(fieldName);
301-
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(documentMapper.mapping(),
302-
documentMapper.mappers(), mapperService.getIndexSettings(), mapperService.getIndexAnalyzers(), null, null, null, null);
299+
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(documentMapper.mappers(),
300+
null, null, null, null);
303301
fieldMapper.processQuery(phraseQuery, parseContext);
304302
ParseContext.Document document = parseContext.doc();
305303

server/src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,8 @@ public DocumentMapper build() {
9797
private final String type;
9898
private final Text typeText;
9999
private final CompressedXContent mappingSource;
100-
private final Mapping mapping;
101100
private final DocumentParser documentParser;
102-
private final MappingLookup fieldMappers;
103-
private final IndexSettings indexSettings;
104-
private final IndexAnalyzers indexAnalyzers;
101+
private final MappingLookup mappingLookup;
105102
private final MetadataFieldMapper[] deleteTombstoneMetadataFieldMappers;
106103
private final MetadataFieldMapper[] noopTombstoneMetadataFieldMappers;
107104

@@ -111,11 +108,8 @@ private DocumentMapper(IndexSettings indexSettings,
111108
Mapping mapping) {
112109
this.type = mapping.root().name();
113110
this.typeText = new Text(this.type);
114-
this.mapping = mapping;
115111
this.documentParser = documentParser;
116-
this.indexSettings = indexSettings;
117-
this.indexAnalyzers = indexAnalyzers;
118-
this.fieldMappers = MappingLookup.fromMapping(mapping, this::parse);
112+
this.mappingLookup = MappingLookup.fromMapping(mapping, documentParser, indexSettings, indexAnalyzers);
119113

120114
try {
121115
mappingSource = new CompressedXContent(this, XContentType.JSON, ToXContent.EMPTY_PARAMS);
@@ -134,7 +128,7 @@ private DocumentMapper(IndexSettings indexSettings,
134128
}
135129

136130
public Mapping mapping() {
137-
return mapping;
131+
return mappingLookup.getMapping();
138132
}
139133

140134
public String type() {
@@ -146,19 +140,19 @@ public Text typeText() {
146140
}
147141

148142
public Map<String, Object> meta() {
149-
return mapping.meta;
143+
return mapping().meta;
150144
}
151145

152146
public CompressedXContent mappingSource() {
153147
return this.mappingSource;
154148
}
155149

156150
public RootObjectMapper root() {
157-
return mapping.root;
151+
return mapping().root;
158152
}
159153

160154
public <T extends MetadataFieldMapper> T metadataMapper(Class<T> type) {
161-
return mapping.metadataMapper(type);
155+
return mapping().metadataMapper(type);
162156
}
163157

164158
public IndexFieldMapper indexMapper() {
@@ -190,24 +184,23 @@ public boolean hasNestedObjects() {
190184
}
191185

192186
public MappingLookup mappers() {
193-
return this.fieldMappers;
187+
return this.mappingLookup;
194188
}
195189

196190
public ParsedDocument parse(SourceToParse source) throws MapperParsingException {
197-
return documentParser.parseDocument(source, mapping, fieldMappers, indexSettings, indexAnalyzers);
191+
return documentParser.parseDocument(source, mappingLookup);
198192
}
199193

200194
public ParsedDocument createDeleteTombstoneDoc(String index, String type, String id) throws MapperParsingException {
201195
final SourceToParse emptySource = new SourceToParse(index, type, id, new BytesArray("{}"), XContentType.JSON);
202-
return documentParser.parseDocument(emptySource, mapping, deleteTombstoneMetadataFieldMappers, fieldMappers,
203-
indexSettings, indexAnalyzers).toTombstone();
196+
return documentParser.parseDocument(emptySource, deleteTombstoneMetadataFieldMappers, mappingLookup).toTombstone();
204197
}
205198

206199
public ParsedDocument createNoopTombstoneDoc(String index, String reason) throws MapperParsingException {
207200
final String id = ""; // _id won't be used.
208201
final SourceToParse sourceToParse = new SourceToParse(index, type, id, new BytesArray("{}"), XContentType.JSON);
209-
final ParsedDocument parsedDoc = documentParser.parseDocument(sourceToParse, mapping, noopTombstoneMetadataFieldMappers,
210-
fieldMappers, indexSettings, indexAnalyzers).toTombstone();
202+
final ParsedDocument parsedDoc = documentParser.parseDocument(sourceToParse, noopTombstoneMetadataFieldMappers, mappingLookup)
203+
.toTombstone();
211204
// Store the reason of a noop as a raw string in the _source field
212205
final BytesRef byteRef = new BytesRef(reason);
213206
parsedDoc.rootDoc().add(new StoredField(SourceFieldMapper.NAME, byteRef.bytes, byteRef.offset, byteRef.length));
@@ -300,12 +293,12 @@ public String getNestedParent(String path) {
300293
}
301294

302295
public DocumentMapper merge(Mapping mapping, MergeReason reason) {
303-
Mapping merged = this.mapping.merge(mapping, reason);
304-
return new DocumentMapper(this.indexSettings, this.indexAnalyzers, this.documentParser, merged);
296+
Mapping merged = this.mapping().merge(mapping, reason);
297+
return new DocumentMapper(mappingLookup.getIndexSettings(), mappingLookup.getIndexAnalyzers(), documentParser, merged);
305298
}
306299

307300
public void validate(IndexSettings settings, boolean checkLimits) {
308-
this.mapping.validate(this.fieldMappers);
301+
this.mapping().validate(this.mappingLookup);
309302
if (settings.getIndexMetadata().isRoutingPartitionedIndex()) {
310303
if (routingFieldMapper().required() == false) {
311304
throw new IllegalArgumentException("mapping type [" + type() + "] must have routing "
@@ -316,13 +309,13 @@ public void validate(IndexSettings settings, boolean checkLimits) {
316309
throw new IllegalArgumentException("cannot have nested fields when index sort is activated");
317310
}
318311
if (checkLimits) {
319-
this.fieldMappers.checkLimits(settings);
312+
this.mappingLookup.checkLimits(settings);
320313
}
321314
}
322315

323316
@Override
324317
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
325-
return mapping.toXContent(builder, params);
318+
return mapping().toXContent(builder, params);
326319
}
327320

328321
@Override
@@ -331,9 +324,8 @@ public String toString() {
331324
"type='" + type + '\'' +
332325
", typeText=" + typeText +
333326
", mappingSource=" + mappingSource +
334-
", mapping=" + mapping +
335327
", documentParser=" + documentParser +
336-
", fieldMappers=" + fieldMappers +
328+
", mappingLookup=" + mappingLookup +
337329
", objectMappers=" + mappers().objectMappers() +
338330
", hasNestedObjects=" + hasNestedObjects() +
339331
", deleteTombstoneMetadataFieldMappers=" + Arrays.toString(deleteTombstoneMetadataFieldMappers) +

server/src/main/java/org/elasticsearch/index/mapper/DocumentParser.java

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@
4040
import org.elasticsearch.common.xcontent.XContentHelper;
4141
import org.elasticsearch.common.xcontent.XContentParser;
4242
import org.elasticsearch.common.xcontent.XContentType;
43-
import org.elasticsearch.index.IndexSettings;
44-
import org.elasticsearch.index.analysis.IndexAnalyzers;
4543
import org.elasticsearch.index.query.QueryShardContext;
4644

4745
/** A parser for documents, given mappings from a DocumentMapper */
@@ -60,34 +58,26 @@ final class DocumentParser {
6058
}
6159

6260
ParsedDocument parseDocument(SourceToParse source,
63-
Mapping mapping,
64-
MappingLookup mappingLookup,
65-
IndexSettings indexSettings,
66-
IndexAnalyzers indexAnalyzers) throws MapperParsingException {
67-
return parseDocument(source, mapping, mapping.metadataMappers, mappingLookup, indexSettings, indexAnalyzers);
61+
MappingLookup mappingLookup) throws MapperParsingException {
62+
return parseDocument(source, mappingLookup.getMapping().metadataMappers, mappingLookup);
6863
}
6964

7065
ParsedDocument parseDocument(SourceToParse source,
71-
Mapping mapping,
7266
MetadataFieldMapper[] metadataFieldsMappers,
73-
MappingLookup mappingLookup,
74-
IndexSettings indexSettings,
75-
IndexAnalyzers indexAnalyzers) throws MapperParsingException {
67+
MappingLookup mappingLookup) throws MapperParsingException {
7668
validateType(source, mappingLookup.getType());
7769
final ParseContext.InternalParseContext context;
7870
final XContentType xContentType = source.getXContentType();
7971
try (XContentParser parser = XContentHelper.createParser(xContentRegistry,
8072
LoggingDeprecationHandler.INSTANCE, source.source(), xContentType)) {
81-
context = new ParseContext.InternalParseContext(mapping,
73+
context = new ParseContext.InternalParseContext(
8274
mappingLookup,
83-
indexSettings,
84-
indexAnalyzers,
8575
dateParserContext,
8676
dynamicRuntimeFieldsBuilder,
8777
source,
8878
parser);
8979
validateStart(parser);
90-
internalParseDocument(mapping.root(), metadataFieldsMappers, context, parser);
80+
internalParseDocument(mappingLookup.getMapping().root(), metadataFieldsMappers, context, parser);
9181
validateEnd(parser);
9282
} catch (Exception e) {
9383
throw wrapInMapperParsingException(source, e);
@@ -99,7 +89,7 @@ ParsedDocument parseDocument(SourceToParse source,
9989

10090
context.postParse();
10191

102-
return parsedDocument(source, context, createDynamicUpdate(mapping, mappingLookup,
92+
return parsedDocument(source, context, createDynamicUpdate(mappingLookup,
10393
context.getDynamicMappers(), context.getDynamicRuntimeFields()));
10494
}
10595

@@ -180,7 +170,6 @@ private static boolean isEmptyDoc(RootObjectMapper root, XContentParser parser)
180170
return false;
181171
}
182172

183-
184173
private static ParsedDocument parsedDocument(SourceToParse source, ParseContext.InternalParseContext context, Mapping update) {
185174
return new ParsedDocument(
186175
context.version(),
@@ -195,7 +184,6 @@ private static ParsedDocument parsedDocument(SourceToParse source, ParseContext.
195184
);
196185
}
197186

198-
199187
private static MapperParsingException wrapInMapperParsingException(SourceToParse source, Exception e) {
200188
// if its already a mapper parsing exception, no need to wrap it...
201189
if (e instanceof MapperParsingException) {
@@ -234,25 +222,23 @@ private static String[] splitAndValidatePath(String fullFieldPath) {
234222
}
235223

236224
/** Creates a Mapping containing any dynamically added fields, or returns null if there were no dynamic mappings. */
237-
static Mapping createDynamicUpdate(Mapping mapping,
238-
MappingLookup mappingLookup,
225+
static Mapping createDynamicUpdate(MappingLookup mappingLookup,
239226
List<Mapper> dynamicMappers,
240227
List<RuntimeFieldType> dynamicRuntimeFields) {
241228
if (dynamicMappers.isEmpty() && dynamicRuntimeFields.isEmpty()) {
242229
return null;
243230
}
244231
RootObjectMapper root;
245232
if (dynamicMappers.isEmpty() == false) {
246-
root = createDynamicUpdate(mapping.root, mappingLookup, dynamicMappers);
233+
root = createDynamicUpdate(mappingLookup, dynamicMappers);
247234
} else {
248-
root = mapping.root.copyAndReset();
235+
root = mappingLookup.getMapping().root().copyAndReset();
249236
}
250237
root.addRuntimeFields(dynamicRuntimeFields);
251-
return mapping.mappingUpdate(root);
238+
return mappingLookup.getMapping().mappingUpdate(root);
252239
}
253240

254-
private static RootObjectMapper createDynamicUpdate(RootObjectMapper root,
255-
MappingLookup mappingLookup,
241+
private static RootObjectMapper createDynamicUpdate(MappingLookup mappingLookup,
256242
List<Mapper> dynamicMappers) {
257243

258244
// We build a mapping by first sorting the mappers, so that all mappers containing a common prefix
@@ -262,7 +248,7 @@ private static RootObjectMapper createDynamicUpdate(RootObjectMapper root,
262248
Iterator<Mapper> dynamicMapperItr = dynamicMappers.iterator();
263249
List<ObjectMapper> parentMappers = new ArrayList<>();
264250
Mapper firstUpdate = dynamicMapperItr.next();
265-
parentMappers.add(createUpdate(root, splitAndValidatePath(firstUpdate.name()), 0, firstUpdate));
251+
parentMappers.add(createUpdate(mappingLookup.getMapping().root(), splitAndValidatePath(firstUpdate.name()), 0, firstUpdate));
266252
Mapper previousMapper = null;
267253
while (dynamicMapperItr.hasNext()) {
268254
Mapper newMapper = dynamicMapperItr.next();
@@ -308,7 +294,6 @@ private static RootObjectMapper createDynamicUpdate(RootObjectMapper root,
308294
return (RootObjectMapper)parentMappers.get(0);
309295
}
310296

311-
312297
private static void popMappers(List<ObjectMapper> parentMappers, int keepBefore, boolean merge) {
313298
assert keepBefore >= 1; // never remove the root mapper
314299
// pop off parent mappers not needed by the current mapper,

server/src/main/java/org/elasticsearch/index/mapper/FieldTypeLookup.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,4 @@ Iterable<MappedFieldType> filter(Predicate<MappedFieldType> predicate) {
167167
return () -> Stream.concat(fullNameToFieldType.values().stream(), dynamicKeyLookup.fieldTypes())
168168
.distinct().filter(predicate).iterator();
169169
}
170-
171-
public String getType() {
172-
return type;
173-
}
174170
}

server/src/main/java/org/elasticsearch/index/mapper/Mapping.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.index.mapper;
2121

22+
import org.elasticsearch.Version;
2223
import org.elasticsearch.common.Strings;
2324
import org.elasticsearch.common.xcontent.ToXContent;
2425
import org.elasticsearch.common.xcontent.ToXContentFragment;
@@ -30,6 +31,7 @@
3031
import java.io.IOException;
3132
import java.io.UncheckedIOException;
3233
import java.util.Arrays;
34+
import java.util.Collections;
3335
import java.util.Comparator;
3436
import java.util.HashMap;
3537
import java.util.Map;
@@ -42,6 +44,11 @@
4244
*/
4345
public final class Mapping implements ToXContentFragment {
4446

47+
public static final Mapping EMPTY = new Mapping(
48+
new RootObjectMapper.Builder("_doc", Version.CURRENT).build(new ContentPath()),
49+
new MetadataFieldMapper[0],
50+
Collections.emptyMap());
51+
4552
final RootObjectMapper root;
4653
final MetadataFieldMapper[] metadataMappers;
4754
final Map<Class<? extends MetadataFieldMapper>, MetadataFieldMapper> metadataMappersMap;

0 commit comments

Comments
 (0)