Skip to content

Commit e8d32af

Browse files
authored
Extract synthetic source logic from DocumentParser (#116049)
1 parent 8dbb25d commit e8d32af

File tree

31 files changed

+2299
-130
lines changed

31 files changed

+2299
-130
lines changed

benchmarks/src/main/java/org/elasticsearch/benchmark/index/mapper/LogsDbDocumentParsingBenchmark.java

Lines changed: 400 additions & 0 deletions
Large diffs are not rendered by default.

modules/data-streams/src/test/java/org/elasticsearch/datastreams/DataStreamGetWriteIndexTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ public void setup() throws Exception {
241241
new MetadataFieldMapper[] { dtfm },
242242
Collections.emptyMap()
243243
);
244-
MappingLookup mappingLookup = MappingLookup.fromMappers(mapping, List.of(dtfm, dateFieldMapper), List.of());
244+
MappingLookup mappingLookup = MappingLookup.fromMappers(mapping, List.of(dtfm, dateFieldMapper), List.of(), null);
245245
indicesService = DataStreamTestHelper.mockIndicesServices(mappingLookup);
246246
}
247247

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.index.mapper;
11+
12+
import org.elasticsearch.core.Nullable;
13+
import org.elasticsearch.index.IndexSettings;
14+
15+
import java.util.HashMap;
16+
import java.util.Map;
17+
18+
/**
19+
* Contains lookup information needed to perform custom synthetic source logic.
20+
* For example fields that use fallback synthetic source implementation or fields that preserve array ordering
21+
* in synthetic source;
22+
*/
23+
public class CustomSyntheticSourceFieldLookup {
24+
private final Map<String, Reason> fieldsWithCustomSyntheticSourceHandling;
25+
26+
public CustomSyntheticSourceFieldLookup(Mapping mapping, @Nullable IndexSettings indexSettings, boolean isSourceSynthetic) {
27+
var fields = new HashMap<String, Reason>();
28+
if (isSourceSynthetic && indexSettings != null) {
29+
populateFields(fields, mapping.getRoot(), indexSettings.sourceKeepMode());
30+
}
31+
this.fieldsWithCustomSyntheticSourceHandling = Map.copyOf(fields);
32+
}
33+
34+
private void populateFields(Map<String, Reason> fields, ObjectMapper currentLevel, Mapper.SourceKeepMode defaultSourceKeepMode) {
35+
if (currentLevel.isEnabled() == false) {
36+
fields.put(currentLevel.fullPath(), Reason.DISABLED_OBJECT);
37+
return;
38+
}
39+
if (sourceKeepMode(currentLevel, defaultSourceKeepMode) == Mapper.SourceKeepMode.ALL) {
40+
fields.put(currentLevel.fullPath(), Reason.SOURCE_KEEP_ALL);
41+
return;
42+
}
43+
if (currentLevel.isNested() == false && sourceKeepMode(currentLevel, defaultSourceKeepMode) == Mapper.SourceKeepMode.ARRAYS) {
44+
fields.put(currentLevel.fullPath(), Reason.SOURCE_KEEP_ARRAYS);
45+
}
46+
47+
for (Mapper child : currentLevel) {
48+
if (child instanceof ObjectMapper objectMapper) {
49+
populateFields(fields, objectMapper, defaultSourceKeepMode);
50+
} else if (child instanceof FieldMapper fieldMapper) {
51+
// The order here is important.
52+
// If fallback logic is used, it should be always correctly marked as FALLBACK_SYNTHETIC_SOURCE.
53+
// This allows us to apply an optimization for SOURCE_KEEP_ARRAYS and don't store arrays that have one element.
54+
// If this order is changed and a field that both has SOURCE_KEEP_ARRAYS and FALLBACK_SYNTHETIC_SOURCE
55+
// is marked as SOURCE_KEEP_ARRAYS we would lose data for this field by applying such an optimization.
56+
if (fieldMapper.syntheticSourceMode() == FieldMapper.SyntheticSourceMode.FALLBACK) {
57+
fields.put(fieldMapper.fullPath(), Reason.FALLBACK_SYNTHETIC_SOURCE);
58+
} else if (sourceKeepMode(fieldMapper, defaultSourceKeepMode) == Mapper.SourceKeepMode.ALL) {
59+
fields.put(fieldMapper.fullPath(), Reason.SOURCE_KEEP_ALL);
60+
} else if (sourceKeepMode(fieldMapper, defaultSourceKeepMode) == Mapper.SourceKeepMode.ARRAYS) {
61+
fields.put(fieldMapper.fullPath(), Reason.SOURCE_KEEP_ARRAYS);
62+
}
63+
}
64+
}
65+
}
66+
67+
private Mapper.SourceKeepMode sourceKeepMode(ObjectMapper mapper, Mapper.SourceKeepMode defaultSourceKeepMode) {
68+
return mapper.sourceKeepMode().orElse(defaultSourceKeepMode);
69+
}
70+
71+
private Mapper.SourceKeepMode sourceKeepMode(FieldMapper mapper, Mapper.SourceKeepMode defaultSourceKeepMode) {
72+
return mapper.sourceKeepMode().orElse(defaultSourceKeepMode);
73+
}
74+
75+
public Map<String, Reason> getFieldsWithCustomSyntheticSourceHandling() {
76+
return fieldsWithCustomSyntheticSourceHandling;
77+
}
78+
79+
/**
80+
* Specifies why this field needs custom handling.
81+
*/
82+
public enum Reason {
83+
SOURCE_KEEP_ARRAYS,
84+
SOURCE_KEEP_ALL,
85+
FALLBACK_SYNTHETIC_SOURCE,
86+
DISABLED_OBJECT
87+
}
88+
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public static DocumentMapper createEmpty(MapperService mapperService) {
4949
mapping,
5050
mapping.toCompressedXContent(),
5151
IndexVersion.current(),
52+
mapperService.getIndexSettings(),
5253
mapperService.getMapperMetrics(),
5354
mapperService.index().getName()
5455
);
@@ -59,12 +60,13 @@ public static DocumentMapper createEmpty(MapperService mapperService) {
5960
Mapping mapping,
6061
CompressedXContent source,
6162
IndexVersion version,
63+
IndexSettings indexSettings,
6264
MapperMetrics mapperMetrics,
6365
String indexName
6466
) {
6567
this.documentParser = documentParser;
6668
this.type = mapping.getRoot().fullPath();
67-
this.mappingLookup = MappingLookup.fromMapping(mapping);
69+
this.mappingLookup = MappingLookup.fromMapping(mapping, indexSettings);
6870
this.mappingSource = source;
6971
this.mapperMetrics = mapperMetrics;
7072
this.indexVersion = version;

0 commit comments

Comments
 (0)