Skip to content

Commit 8fb6ad6

Browse files
David JuliaDavid Julia
David Julia
authored and
David Julia
committed
Fix Regression in generating queries with nested maps with numeric keys
While maps that have numeric keys work if there is only one map with an integer key, when there are multiple maps with numeric keys in a given query, it fails. Take the following example for a map called outer with numeric keys holding reference to another object with a map called inner with numeric keys: Updates that are meant to generate {"$set": {"outerMap.1234.inner.5678": "hello"}} are instead generating {"$set": {"outerMap.1234.inner.inner": "hello"}}, repeating the later map property name instead of using the integer key value. This commit adds unit tests both for the UpdateMapper and QueryMapper, which check multiple consecutive maps with numeric keys, and adds a fix in the KeyMapper. Because we cannot easily change the path parsing to somehow parse path parts corresponding to map keys differently, we address the issue in the KeyMapper. We keep track of the partial path corresponding to the current property and use it to skip adding the duplicated property name for the map to the query, and instead add the key. This is a bit redundant in that we now have both an iterator and an index-based way of accessing the path parts, but it gets the tests passing and fixes the issue without making a large change to the current approach. There certainly is room to refactor this according to the maintainers' preference. fixes spring-projects#3688
1 parent c5082fb commit 8fb6ad6

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,13 +1392,13 @@ protected String mapPropertyName(MongoPersistentProperty property) {
13921392
String partial = iterator.next();
13931393
currentIndex++;
13941394

1395-
boolean isPositional = isPositionalParameter(partial) && property.isCollectionLike() ;
1396-
if(property.isMap() && currentPropertyRoot.equals(partial)){
1395+
boolean isPositional = isPositionalParameter(partial) && property.isCollectionLike();
1396+
if(property.isMap() && currentPropertyRoot.equals(partial) && iterator.hasNext()){
13971397
partial = iterator.next();
13981398
currentIndex++;
13991399
}
14001400

1401-
if (isPositional || property.isMap()) {
1401+
if (isPositional || property.isMap() && iterator.hasNext()) {
14021402
mappedName.append(".").append(partial);
14031403
}
14041404

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,17 @@ void mappingShouldRetainNestedNumericMapKeys() {
751751
assertThat(document).containsKey("outerMap.1.map.2.stringProperty");
752752
}
753753

754+
@Test // GH-3688
755+
void mappingShouldAllowSettingEntireNestedNumericKeyedMapValue() {
756+
757+
Query query = query(where("outerMap.1.map").is(null)); //newEntityWithComplexValueTypeMap()
758+
759+
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
760+
context.getPersistentEntity(EntityWithIntKeyedMapOfMap.class));
761+
762+
assertThat(document).containsKey("outerMap.1.map");
763+
}
764+
754765
@Test // DATAMONGO-1269
755766
void mappingShouldRetainNumericPositionInList() {
756767

0 commit comments

Comments
 (0)