Skip to content

Commit bae09a8

Browse files
authored
[8.x] Reset array scope tracking for nested objects (elastic#114891) (elastic#114906)
* Reset array scope tracking for nested objects (elastic#114891) * Reset array scope tracking for nested objects * update * update * update (cherry picked from commit 8ae5ca4) # Conflicts: # muted-tests.yml * update * update
1 parent 322b095 commit bae09a8

File tree

2 files changed

+46
-9
lines changed

2 files changed

+46
-9
lines changed

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

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public int get() {
111111
private final Set<String> ignoredFields;
112112
private final List<IgnoredSourceFieldMapper.NameValue> ignoredFieldValues;
113113
private final List<IgnoredSourceFieldMapper.NameValue> ignoredFieldsMissingValues;
114-
private final boolean inArrayScopeEnabled;
114+
private boolean inArrayScopeEnabled;
115115
private boolean inArrayScope;
116116

117117
private final Map<String, List<Mapper>> dynamicMappers;
@@ -376,13 +376,14 @@ public final Collection<IgnoredSourceFieldMapper.NameValue> getIgnoredFieldsMiss
376376
* Applies to synthetic source only.
377377
*/
378378
public final DocumentParserContext maybeCloneForArray(Mapper mapper) throws IOException {
379-
if (canAddIgnoredField() && mapper instanceof ObjectMapper && inArrayScopeEnabled) {
380-
boolean isNested = mapper instanceof NestedObjectMapper;
381-
if ((inArrayScope == false && isNested == false) || (inArrayScope && isNested)) {
382-
DocumentParserContext subcontext = switchParser(parser());
383-
subcontext.inArrayScope = inArrayScope == false;
384-
return subcontext;
385-
}
379+
if (canAddIgnoredField()
380+
&& mapper instanceof ObjectMapper
381+
&& mapper instanceof NestedObjectMapper == false
382+
&& inArrayScope == false
383+
&& inArrayScopeEnabled) {
384+
DocumentParserContext subcontext = switchParser(parser());
385+
subcontext.inArrayScope = true;
386+
return subcontext;
386387
}
387388
return this;
388389
}
@@ -709,12 +710,18 @@ public final DocumentParserContext createNestedContext(NestedObjectMapper nested
709710
* Return a new context that has the provided document as the current document.
710711
*/
711712
public final DocumentParserContext switchDoc(final LuceneDocument document) {
712-
return new Wrapper(this.parent, this) {
713+
DocumentParserContext cloned = new Wrapper(this.parent, this) {
713714
@Override
714715
public LuceneDocument doc() {
715716
return document;
716717
}
717718
};
719+
// Disable tracking array scopes for ignored source, as it would be added to the parent doc.
720+
// Nested documents are added to preserve object structure within arrays of objects, so the use
721+
// of ignored source for arrays inside them should be mostly redundant.
722+
cloned.inArrayScope = false;
723+
cloned.inArrayScopeEnabled = false;
724+
return cloned;
718725
}
719726

720727
/**

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,36 @@ public void testConflictingFieldNameAfterArray() throws IOException {
932932
{"path":{"id":0.1,"to":{"id":[1,20,3,10]}}}""", syntheticSource);
933933
}
934934

935+
public void testArrayWithNestedObjects() throws IOException {
936+
DocumentMapper documentMapper = createMapperService(syntheticSourceMapping(b -> {
937+
b.startObject("path").startObject("properties");
938+
{
939+
b.startObject("to").field("type", "nested").startObject("properties");
940+
{
941+
b.startObject("id").field("type", "integer").field("synthetic_source_keep", "arrays").endObject();
942+
}
943+
b.endObject().endObject();
944+
}
945+
b.endObject().endObject();
946+
})).documentMapper();
947+
948+
var syntheticSource = syntheticSource(documentMapper, b -> {
949+
b.startArray("path");
950+
{
951+
b.startObject().startArray("to");
952+
{
953+
b.startObject().array("id", 1, 20, 3).endObject();
954+
b.startObject().field("id", 10).endObject();
955+
}
956+
b.endArray().endObject();
957+
b.startObject().startObject("to").field("id", "0.1").endObject().endObject();
958+
}
959+
b.endArray();
960+
});
961+
assertEquals("""
962+
{"path":{"to":[{"id":[1,20,3]},{"id":10},{"id":0}]}}""", syntheticSource);
963+
}
964+
935965
public void testArrayWithinArray() throws IOException {
936966
DocumentMapper documentMapper = createMapperService(syntheticSourceMapping(b -> {
937967
b.startObject("path");

0 commit comments

Comments
 (0)