Skip to content

Commit f3cd890

Browse files
authored
Second parsing pass tracks array scopes properly (#114621)
1 parent f77611c commit f3cd890

File tree

3 files changed

+38
-11
lines changed

3 files changed

+38
-11
lines changed

muted-tests.yml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -372,15 +372,6 @@ tests:
372372
- class: org.elasticsearch.backwards.MixedClusterClientYamlTestSuiteIT
373373
method: test {p0=synonyms/60_synonym_rule_get/Synonym rule not found}
374374
issue: https://github.com/elastic/elasticsearch/issues/114444
375-
- class: org.elasticsearch.datastreams.logsdb.qa.LogsDbVersusLogsDbReindexedIntoStandardModeChallengeRestIT
376-
method: testTermsAggregation
377-
issue: https://github.com/elastic/elasticsearch/issues/114554
378-
- class: org.elasticsearch.datastreams.logsdb.qa.LogsDbVersusLogsDbReindexedIntoStandardModeChallengeRestIT
379-
method: testTermsQuery
380-
issue: https://github.com/elastic/elasticsearch/issues/114563
381-
- class: org.elasticsearch.datastreams.logsdb.qa.LogsDbVersusLogsDbReindexedIntoStandardModeChallengeRestIT
382-
method: testMatchAllQuery
383-
issue: https://github.com/elastic/elasticsearch/issues/114607
384375
- class: org.elasticsearch.xpack.esql.optimizer.PhysicalPlanOptimizerTests
385376
method: testPushSpatialIntersectsEvalToSource {default}
386377
issue: https://github.com/elastic/elasticsearch/issues/114627

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ private static List<IgnoredSourceFieldMapper.NameValue> parseDocForMissingValues
208208
XContentParser parser = context.parser();
209209
XContentParser.Token currentToken = parser.nextToken();
210210
List<String> path = new ArrayList<>();
211+
List<Boolean> isObjectInPath = new ArrayList<>(); // Tracks if path components correspond to an object or an array.
211212
String fieldName = null;
212213
while (currentToken != null) {
213214
while (currentToken != XContentParser.Token.FIELD_NAME) {
@@ -218,11 +219,16 @@ private static List<IgnoredSourceFieldMapper.NameValue> parseDocForMissingValues
218219
parser.skipChildren();
219220
} else {
220221
path.add(fieldName);
222+
isObjectInPath.add(currentToken == XContentParser.Token.START_OBJECT);
221223
}
222224
fieldName = null;
223225
} else if (currentToken == XContentParser.Token.END_OBJECT || currentToken == XContentParser.Token.END_ARRAY) {
224-
if (currentToken == XContentParser.Token.END_OBJECT && path.isEmpty() == false) {
226+
// Remove the path, if the scope type matches the one when the path was added.
227+
if (isObjectInPath.isEmpty() == false
228+
&& (isObjectInPath.getLast() && currentToken == XContentParser.Token.END_OBJECT
229+
|| isObjectInPath.getLast() == false && currentToken == XContentParser.Token.END_ARRAY)) {
225230
path.removeLast();
231+
isObjectInPath.removeLast();
226232
}
227233
fieldName = null;
228234
}
@@ -237,7 +243,6 @@ private static List<IgnoredSourceFieldMapper.NameValue> parseDocForMissingValues
237243
if (leaf != null) {
238244
parser.nextToken(); // Advance the parser to the value to be read.
239245
result.add(leaf.cloneWithValue(context.encodeFlattenedToken()));
240-
parser.nextToken(); // Skip the token ending the value.
241246
fieldName = null;
242247
}
243248
currentToken = parser.nextToken();

server/src/test/java/org/elasticsearch/index/mapper/IgnoredSourceFieldMapperTests.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,37 @@ public void testNestedArray() throws IOException {
901901
);
902902
}
903903

904+
public void testConflictingFieldNameAfterArray() throws IOException {
905+
DocumentMapper documentMapper = createMapperService(syntheticSourceMapping(b -> {
906+
b.startObject("path").startObject("properties");
907+
{
908+
b.startObject("to").startObject("properties");
909+
{
910+
b.startObject("id").field("type", "integer").field("synthetic_source_keep", "arrays").endObject();
911+
}
912+
b.endObject().endObject();
913+
b.startObject("id").field("type", "float").endObject();
914+
}
915+
b.endObject().endObject();
916+
})).documentMapper();
917+
918+
var syntheticSource = syntheticSource(documentMapper, b -> {
919+
b.startObject("path");
920+
{
921+
b.startArray("to");
922+
{
923+
b.startObject().array("id", 1, 20, 3).endObject();
924+
b.startObject().field("id", 10).endObject();
925+
}
926+
b.endArray();
927+
b.field("id", "0.1");
928+
}
929+
b.endObject();
930+
});
931+
assertEquals("""
932+
{"path":{"id":0.1,"to":{"id":[1,20,3,10]}}}""", syntheticSource);
933+
}
934+
904935
public void testArrayWithinArray() throws IOException {
905936
DocumentMapper documentMapper = createMapperService(syntheticSourceMapping(b -> {
906937
b.startObject("path");

0 commit comments

Comments
 (0)