From 7dfe4604336ab79a1ee7cde721254be6a5e41906 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 21 Jun 2021 12:24:02 +0200 Subject: [PATCH] Fix field projection value conversion. The field projection conversion should actually only map field names and avoid value conversion. In the MongoId case an inclusion parameter (1) was unintentionally converted into its String representation which causes trouble on Mongo 4.4 servers. Fixes: #3668 Original pull request: #3678. --- .../mongodb/core/convert/QueryMapper.java | 37 +++++++++++-------- .../core/convert/QueryMapperUnitTests.java | 14 +++++++ 2 files changed, 35 insertions(+), 16 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 0392dc542..08f6458e9 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 @@ -195,19 +195,7 @@ public class QueryMapper { return new Document(); } - sortObject = filterUnwrappedObjects(sortObject, entity); - - Document mappedSort = new Document(); - for (Map.Entry entry : BsonUtils.asMap(sortObject).entrySet()) { - - Field field = createPropertyField(entity, entry.getKey(), mappingContext); - if (field.getProperty() != null && field.getProperty().isUnwrapped()) { - continue; - } - - mappedSort.put(field.getMappedKey(), entry.getValue()); - } - + Document mappedSort = mapFieldsToPropertyNames(sortObject, entity); mapMetaAttributes(mappedSort, entity, MetaMapping.WHEN_PRESENT); return mappedSort; } @@ -225,13 +213,30 @@ public class QueryMapper { Assert.notNull(fieldsObject, "FieldsObject must not be null!"); - fieldsObject = filterUnwrappedObjects(fieldsObject, entity); - - Document mappedFields = getMappedObject(fieldsObject, entity); + Document mappedFields = mapFieldsToPropertyNames(fieldsObject, entity); mapMetaAttributes(mappedFields, entity, MetaMapping.FORCE); return mappedFields; } + private Document mapFieldsToPropertyNames(Document fields, @Nullable MongoPersistentEntity entity) { + + if (fields.isEmpty()) { + return new Document(); + + } + Document target = new Document(); + for (Map.Entry entry : BsonUtils.asMap(filterUnwrappedObjects(fields, entity)).entrySet()) { + + Field field = createPropertyField(entity, entry.getKey(), mappingContext); + if (field.getProperty() != null && field.getProperty().isUnwrapped()) { + continue; + } + + target.put(field.getMappedKey(), entry.getValue()); + } + return target; + } + private void mapMetaAttributes(Document source, @Nullable MongoPersistentEntity entity, MetaMapping metaMapping) { if (entity == null) { 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 770f8ebe2..ba883d14c 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 @@ -50,6 +50,7 @@ import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.FieldType; +import org.springframework.data.mongodb.core.mapping.MongoId; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.TextScore; @@ -1304,6 +1305,13 @@ public class QueryMapperUnitTests { assertThat(mapper.getMappedSort(query.getQueryObject(), context.getPersistentEntity(Customer.class))).isEqualTo(new org.bson.Document("address.street", "1007 Mountain Drive")); } + @Test // GH-3668 + void mapStringIdFieldProjection() { + + org.bson.Document mappedFields = mapper.getMappedFields(new org.bson.Document("id", 1), context.getPersistentEntity(WithStringId.class)); + assertThat(mappedFields).containsEntry("_id", 1); + } + class WithDeepArrayNesting { List level0; @@ -1367,6 +1375,12 @@ public class QueryMapperUnitTests { @Id private String foo; } + class WithStringId { + + @MongoId String id; + String name; + } + class BigIntegerId { @Id private BigInteger id;