Skip to content

Commit df7041f

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 a8757f9 commit df7041f

File tree

19 files changed

+241
-282
lines changed

19 files changed

+241
-282
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1113,8 +1113,8 @@ private void duelRun(PercolateQuery.QueryStore queryStore, MemoryIndex memoryInd
11131113
}
11141114

11151115
private void addQuery(Query query, List<ParseContext.Document> docs) {
1116-
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(documentMapper.mapping(),
1117-
documentMapper.mappers(), mapperService.getIndexSettings(), mapperService.getIndexAnalyzers(), null, null, null, null);
1116+
ParseContext.InternalParseContext parseContext = new ParseContext.InternalParseContext(
1117+
documentMapper.mappers(), null, null, null, null);
11181118
fieldMapper.processQuery(query, parseContext);
11191119
ParseContext.Document queryDocument = parseContext.doc();
11201120
// Add to string representation of the query to make debugging easier:

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

+10-12
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ public void testExtractTerms() throws Exception {
181181

182182
DocumentMapper documentMapper = mapperService.documentMapper();
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();
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();
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();
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

+16-23
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,8 @@ public DocumentMapper build() {
9696
private final String type;
9797
private final Text typeText;
9898
private final CompressedXContent mappingSource;
99-
private final Mapping mapping;
10099
private final DocumentParser documentParser;
101-
private final MappingLookup fieldMappers;
102-
private final IndexSettings indexSettings;
103-
private final IndexAnalyzers indexAnalyzers;
100+
private final MappingLookup mappingLookup;
104101
private final MetadataFieldMapper[] deleteTombstoneMetadataFieldMappers;
105102
private final MetadataFieldMapper[] noopTombstoneMetadataFieldMappers;
106103

@@ -110,11 +107,8 @@ private DocumentMapper(IndexSettings indexSettings,
110107
Mapping mapping) {
111108
this.type = mapping.root().name();
112109
this.typeText = new Text(this.type);
113-
this.mapping = mapping;
114110
this.documentParser = documentParser;
115-
this.indexSettings = indexSettings;
116-
this.indexAnalyzers = indexAnalyzers;
117-
this.fieldMappers = MappingLookup.fromMapping(mapping, this::parse);
111+
this.mappingLookup = MappingLookup.fromMapping(mapping, documentParser, indexSettings, indexAnalyzers);
118112

119113
try {
120114
mappingSource = new CompressedXContent(this, XContentType.JSON, ToXContent.EMPTY_PARAMS);
@@ -133,7 +127,7 @@ private DocumentMapper(IndexSettings indexSettings,
133127
}
134128

135129
public Mapping mapping() {
136-
return mapping;
130+
return mappingLookup.getMapping();
137131
}
138132

139133
public String type() {
@@ -145,19 +139,19 @@ public Text typeText() {
145139
}
146140

147141
public Map<String, Object> meta() {
148-
return mapping.meta;
142+
return mapping().meta;
149143
}
150144

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

155149
public RootObjectMapper root() {
156-
return mapping.root;
150+
return mapping().root;
157151
}
158152

159153
public <T extends MetadataFieldMapper> T metadataMapper(Class<T> type) {
160-
return mapping.metadataMapper(type);
154+
return mapping().metadataMapper(type);
161155
}
162156

163157
public SourceFieldMapper sourceMapper() {
@@ -181,24 +175,23 @@ public boolean hasNestedObjects() {
181175
}
182176

183177
public MappingLookup mappers() {
184-
return this.fieldMappers;
178+
return this.mappingLookup;
185179
}
186180

187181
public ParsedDocument parse(SourceToParse source) throws MapperParsingException {
188-
return documentParser.parseDocument(source, mapping, fieldMappers, indexSettings, indexAnalyzers);
182+
return documentParser.parseDocument(source, mappingLookup);
189183
}
190184

191185
public ParsedDocument createDeleteTombstoneDoc(String index, String id) throws MapperParsingException {
192186
final SourceToParse emptySource = new SourceToParse(index, id, new BytesArray("{}"), XContentType.JSON);
193-
return documentParser.parseDocument(emptySource, mapping, deleteTombstoneMetadataFieldMappers, fieldMappers,
194-
indexSettings, indexAnalyzers).toTombstone();
187+
return documentParser.parseDocument(emptySource, deleteTombstoneMetadataFieldMappers, mappingLookup).toTombstone();
195188
}
196189

197190
public ParsedDocument createNoopTombstoneDoc(String index, String reason) throws MapperParsingException {
198191
final String id = ""; // _id won't be used.
199192
final SourceToParse sourceToParse = new SourceToParse(index, id, new BytesArray("{}"), XContentType.JSON);
200-
final ParsedDocument parsedDoc = documentParser.parseDocument(sourceToParse, mapping, noopTombstoneMetadataFieldMappers,
201-
fieldMappers, indexSettings, indexAnalyzers).toTombstone();
193+
final ParsedDocument parsedDoc = documentParser.parseDocument(sourceToParse, noopTombstoneMetadataFieldMappers, mappingLookup)
194+
.toTombstone();
202195
// Store the reason of a noop as a raw string in the _source field
203196
final BytesRef byteRef = new BytesRef(reason);
204197
parsedDoc.rootDoc().add(new StoredField(SourceFieldMapper.NAME, byteRef.bytes, byteRef.offset, byteRef.length));
@@ -291,12 +284,12 @@ public String getNestedParent(String path) {
291284
}
292285

293286
public DocumentMapper merge(Mapping mapping, MergeReason reason) {
294-
Mapping merged = this.mapping.merge(mapping, reason);
295-
return new DocumentMapper(this.indexSettings, this.indexAnalyzers, this.documentParser, merged);
287+
Mapping merged = this.mapping().merge(mapping, reason);
288+
return new DocumentMapper(mappingLookup.getIndexSettings(), mappingLookup.getIndexAnalyzers(), documentParser, merged);
296289
}
297290

298291
public void validate(IndexSettings settings, boolean checkLimits) {
299-
this.mapping.validate(this.fieldMappers);
292+
this.mapping().validate(this.mappingLookup);
300293
if (settings.getIndexMetadata().isRoutingPartitionedIndex()) {
301294
if (routingFieldMapper().required() == false) {
302295
throw new IllegalArgumentException("mapping type [" + type() + "] must have routing "
@@ -307,12 +300,12 @@ public void validate(IndexSettings settings, boolean checkLimits) {
307300
throw new IllegalArgumentException("cannot have nested fields when index sort is activated");
308301
}
309302
if (checkLimits) {
310-
this.fieldMappers.checkLimits(settings);
303+
this.mappingLookup.checkLimits(settings);
311304
}
312305
}
313306

314307
@Override
315308
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
316-
return mapping.toXContent(builder, params);
309+
return mapping().toXContent(builder, params);
317310
}
318311
}

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

+12-27
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,33 +58,25 @@ 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
final ParseContext.InternalParseContext context;
7769
final XContentType xContentType = source.getXContentType();
7870
try (XContentParser parser = XContentHelper.createParser(xContentRegistry,
7971
LoggingDeprecationHandler.INSTANCE, source.source(), xContentType)) {
80-
context = new ParseContext.InternalParseContext(mapping,
72+
context = new ParseContext.InternalParseContext(
8173
mappingLookup,
82-
indexSettings,
83-
indexAnalyzers,
8474
dateParserContext,
8575
dynamicRuntimeFieldsBuilder,
8676
source,
8777
parser);
8878
validateStart(parser);
89-
internalParseDocument(mapping.root(), metadataFieldsMappers, context, parser);
79+
internalParseDocument(mappingLookup.getMapping().root(), metadataFieldsMappers, context, parser);
9080
validateEnd(parser);
9181
} catch (Exception e) {
9282
throw wrapInMapperParsingException(source, e);
@@ -98,7 +88,7 @@ ParsedDocument parseDocument(SourceToParse source,
9888

9989
context.postParse();
10090

101-
return parsedDocument(source, context, createDynamicUpdate(mapping, mappingLookup,
91+
return parsedDocument(source, context, createDynamicUpdate(mappingLookup,
10292
context.getDynamicMappers(), context.getDynamicRuntimeFields()));
10393
}
10494

@@ -168,7 +158,6 @@ private static boolean isEmptyDoc(RootObjectMapper root, XContentParser parser)
168158
return false;
169159
}
170160

171-
172161
private static ParsedDocument parsedDocument(SourceToParse source, ParseContext.InternalParseContext context, Mapping update) {
173162
return new ParsedDocument(
174163
context.version(),
@@ -182,7 +171,6 @@ private static ParsedDocument parsedDocument(SourceToParse source, ParseContext.
182171
);
183172
}
184173

185-
186174
private static MapperParsingException wrapInMapperParsingException(SourceToParse source, Exception e) {
187175
// if its already a mapper parsing exception, no need to wrap it...
188176
if (e instanceof MapperParsingException) {
@@ -221,25 +209,23 @@ private static String[] splitAndValidatePath(String fullFieldPath) {
221209
}
222210

223211
/** Creates a Mapping containing any dynamically added fields, or returns null if there were no dynamic mappings. */
224-
static Mapping createDynamicUpdate(Mapping mapping,
225-
MappingLookup mappingLookup,
212+
static Mapping createDynamicUpdate(MappingLookup mappingLookup,
226213
List<Mapper> dynamicMappers,
227214
List<RuntimeFieldType> dynamicRuntimeFields) {
228215
if (dynamicMappers.isEmpty() && dynamicRuntimeFields.isEmpty()) {
229216
return null;
230217
}
231218
RootObjectMapper root;
232219
if (dynamicMappers.isEmpty() == false) {
233-
root = createDynamicUpdate(mapping.root, mappingLookup, dynamicMappers);
220+
root = createDynamicUpdate(mappingLookup, dynamicMappers);
234221
} else {
235-
root = mapping.root.copyAndReset();
222+
root = mappingLookup.getMapping().root().copyAndReset();
236223
}
237224
root.addRuntimeFields(dynamicRuntimeFields);
238-
return mapping.mappingUpdate(root);
225+
return mappingLookup.getMapping().mappingUpdate(root);
239226
}
240227

241-
private static RootObjectMapper createDynamicUpdate(RootObjectMapper root,
242-
MappingLookup mappingLookup,
228+
private static RootObjectMapper createDynamicUpdate(MappingLookup mappingLookup,
243229
List<Mapper> dynamicMappers) {
244230

245231
// We build a mapping by first sorting the mappers, so that all mappers containing a common prefix
@@ -249,7 +235,7 @@ private static RootObjectMapper createDynamicUpdate(RootObjectMapper root,
249235
Iterator<Mapper> dynamicMapperItr = dynamicMappers.iterator();
250236
List<ObjectMapper> parentMappers = new ArrayList<>();
251237
Mapper firstUpdate = dynamicMapperItr.next();
252-
parentMappers.add(createUpdate(root, splitAndValidatePath(firstUpdate.name()), 0, firstUpdate));
238+
parentMappers.add(createUpdate(mappingLookup.getMapping().root(), splitAndValidatePath(firstUpdate.name()), 0, firstUpdate));
253239
Mapper previousMapper = null;
254240
while (dynamicMapperItr.hasNext()) {
255241
Mapper newMapper = dynamicMapperItr.next();
@@ -295,7 +281,6 @@ private static RootObjectMapper createDynamicUpdate(RootObjectMapper root,
295281
return (RootObjectMapper)parentMappers.get(0);
296282
}
297283

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

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

+7
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
import java.io.IOException;
2525
import java.io.UncheckedIOException;
2626
import java.util.Arrays;
27+
import java.util.Collections;
2728
import java.util.Comparator;
2829
import java.util.HashMap;
2930
import java.util.Map;
3031

32+
import org.elasticsearch.Version;
3133
import org.elasticsearch.common.Strings;
3234
import org.elasticsearch.common.xcontent.ToXContent;
3335
import org.elasticsearch.common.xcontent.ToXContentFragment;
@@ -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)