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 cf0a02bbf..b104404b7 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 @@ -66,6 +66,7 @@ import com.mongodb.DBRef; * @author Thomas Darimont * @author Christoph Strobl * @author Mark Paluch + * @author David Julia */ public class QueryMapper { @@ -1273,11 +1274,17 @@ public class QueryMapper { static class KeyMapper { private final Iterator iterator; + private int currentIndex; + private String currentPropertyRoot; + private final List pathParts; public KeyMapper(String key, MappingContext, MongoPersistentProperty> mappingContext) { - this.iterator = Arrays.asList(key.split("\\.")).iterator(); + this.pathParts = Arrays.asList(key.split("\\.")); + this.currentPropertyRoot = pathParts.get(0); + this.currentIndex = 0; + this.iterator = pathParts.iterator(); this.iterator.next(); } @@ -1295,16 +1302,25 @@ public class QueryMapper { while (inspect) { String partial = iterator.next(); + currentIndex++; - boolean isPositional = isPositionalParameter(partial) && property.isCollectionLike(); + boolean isPositional = isPositionalParameter(partial) && property.isCollectionLike() ; + if(property.isMap() && currentPropertyRoot.equals(partial) && iterator.hasNext()){ + partial = iterator.next(); + currentIndex++; + } - if (isPositional || property.isMap()) { + if (isPositional || property.isMap() && !currentPropertyRoot.equals(partial)) { mappedName.append(".").append(partial); } inspect = isPositional && iterator.hasNext(); } + if(currentIndex + 1 < pathParts.size()) { + currentIndex++; + currentPropertyRoot = pathParts.get(currentIndex); + } return mappedName.toString(); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index 78405deb3..c6dccb829 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -75,6 +75,7 @@ import com.mongodb.client.model.Filters; * @author Thomas Darimont * @author Christoph Strobl * @author Mark Paluch + * @author David Julia */ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) @@ -737,6 +738,28 @@ public class QueryMapperUnitTests { assertThat(document).containsKey("map.1.stringProperty"); } + @Test // GH-3688 + void mappingShouldRetainNestedNumericMapKeys() { + + Query query = query(where("outerMap.1.map.2.stringProperty").is("ba'alzamon")); + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(EntityWithIntKeyedMapOfMap.class)); + + assertThat(document).containsKey("outerMap.1.map.2.stringProperty"); + } + + @Test // GH-3688 + void mappingShouldAllowSettingEntireNestedNumericKeyedMapValue() { + + Query query = query(where("outerMap.1.map").is(null)); //newEntityWithComplexValueTypeMap() + + org.bson.Document document = mapper.getMappedObject(query.getQueryObject(), + context.getPersistentEntity(EntityWithIntKeyedMapOfMap.class)); + + assertThat(document).containsKey("outerMap.1.map"); + } + @Test // DATAMONGO-1269 void mappingShouldRetainNumericPositionInList() { @@ -1278,6 +1301,10 @@ public class QueryMapperUnitTests { Map map; } + static class EntityWithIntKeyedMapOfMap{ + Map outerMap; + } + static class EntityWithComplexValueTypeList { List list; } 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 ec43ae33e..fa9ac1547 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 @@ -65,6 +65,7 @@ import com.mongodb.DBRef; * @author Thomas Darimont * @author Mark Paluch * @author Pavel Vodrazka + * @author David Julia */ @ExtendWith(MockitoExtension.class) class UpdateMapperUnitTests { @@ -1110,6 +1111,16 @@ class UpdateMapperUnitTests { .isEqualTo("{\"$set\": {\"map.601218778970110001827396.value\": \"testing\"}}"); } + @Test // GH-3688 + void multipleNumericKeysInNestedPath() { + + Update update = new Update().set("intKeyedMap.12345.map.0", "testing"); + Document mappedUpdate = mapper.getMappedObject(update.getUpdateObject(), + context.getPersistentEntity(EntityWithIntKeyedMap.class)); + + assertThat(mappedUpdate).isEqualTo("{\"$set\": {\"intKeyedMap.12345.map.0\": \"testing\"}}"); + } + @Test // GH-3566 void mapsObjectClassPropertyFieldInMapValueTypeAsKey() { @@ -1357,6 +1368,10 @@ class UpdateMapperUnitTests { Map concreteMap; } + static class EntityWithIntKeyedMap{ + Map intKeyedMap; + } + static class ClassWithEnum { Allocation allocation;