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 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; + } }