From 390c37f0687fcfca0daf499b3e1d48bf5a132654 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 11 Jan 2022 11:06:35 +0100 Subject: [PATCH 1/2] Prepare issue branch. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 63af8ca470..3e4fd1df9a 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.4.0-SNAPSHOT + 3.4.0-GH-3921-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index e2704a6753..38d850ec60 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 3.4.0-SNAPSHOT + 3.4.0-GH-3921-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index b75f8bf624..6766c0bec9 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 3.4.0-SNAPSHOT + 3.4.0-GH-3921-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index ca96626cc9..b3165972f2 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.4.0-SNAPSHOT + 3.4.0-GH-3921-SNAPSHOT ../pom.xml From 1f6cb3ae936cb411aa6cbd61ba123bbc8fc5077e Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 11 Jan 2022 13:06:02 +0100 Subject: [PATCH 2/2] Use index instead of iterator to map position and map keys for updates. This commit removes usage of the iterator and replaces map key and positional parameter mappings with an index based token lookup. --- .../mongodb/core/convert/QueryMapper.java | 42 +++++++++-------- .../core/convert/UpdateMapperUnitTests.java | 46 +++++++++++++++++++ 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index a360b8be91..1013628de8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -1411,6 +1411,14 @@ public KeyMapper(String key, this.currentIndex = 0; } + String nextToken() { + return pathParts.get(currentIndex+1); + } + + boolean hasNexToken() { + return pathParts.size() > currentIndex+1; + } + /** * Maps the property name while retaining potential positional operator {@literal $}. * @@ -1420,31 +1428,25 @@ public KeyMapper(String key, protected String mapPropertyName(MongoPersistentProperty property) { StringBuilder mappedName = new StringBuilder(PropertyToFieldNameConverter.INSTANCE.convert(property)); + if(!hasNexToken()) { + return mappedName.toString(); + } - boolean inspect = iterator.hasNext(); - - while (inspect) { - - String partial = iterator.next(); - currentIndex++; - - boolean isPositional = isPositionalParameter(partial) && property.isCollectionLike(); - if (property.isMap() && currentPropertyRoot.equals(partial) && iterator.hasNext()) { - partial = iterator.next(); - currentIndex++; - } - - if (isPositional || property.isMap() && !currentPropertyRoot.equals(partial)) { - mappedName.append(".").append(partial); - } + String nextToken = nextToken(); + if(isPositionalParameter(nextToken)) { - inspect = isPositional && iterator.hasNext(); + mappedName.append(".").append(nextToken); + currentIndex+=2; + return mappedName.toString(); } - if (currentIndex + 1 < pathParts.size()) { - currentIndex++; - currentPropertyRoot = pathParts.get(currentIndex); + if(property.isMap()) { + + mappedName.append(".").append(nextToken); + currentIndex+=2; + return mappedName.toString(); } + currentIndex++; return mappedName.toString(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java index 15704af030..28d522fba9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/UpdateMapperUnitTests.java @@ -1309,6 +1309,36 @@ void updateListWithDocuRefOnProperty() { assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("customers", Arrays.asList("c-name")))); } + @Test // GH-3921 + void mapNumericKeyInPathHavingComplexMapValyeTypes() { + + Update update = new Update().set("testInnerData.testMap.1.intValue", "4"); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(TestData.class)); + + assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("testInnerData.testMap.1.intValue","4"))); + } + + @Test // GH-3921 + void mapNumericKeyInPathNotMatchingExistingProperties() { + + Update update = new Update().set("testInnerData.imaginaryMap.1.nonExistingProperty", "4"); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(TestData.class)); + + assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("testInnerData.imaginaryMap.1.noExistingProperty","4"))); + } + + @Test // GH-3921 + void mapNumericKeyInPathPartiallyMatchingExistingProperties() { + + Update update = new Update().set("testInnerData.testMap.1.nonExistingProperty.2.someValue", "4"); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(TestData.class)); + + assertThat(mappedUpdate).isEqualTo(new org.bson.Document("$set",new org.bson.Document("testInnerData.testMap.1.nonExistingProperty.2.someValue","4"))); + } + static class DomainTypeWrappingConcreteyTypeHavingListOfInterfaceTypeAttributes { ListModelWrapper concreteTypeWithListAttributeOfInterfaceType; } @@ -1710,4 +1740,20 @@ static class WithDocumentReference { private List samples; } + @Data + private static class TestData { + @Id + private String id; + private TestInnerData testInnerData; + } + + @Data + private static class TestInnerData { + private Map testMap; + } + + @Data + private static class TestValue { + private int intValue; + } }