Skip value conversion of Pattern and BsonRegularExpression in QueryMapper.
QueryMapper no longer attempts to convert regex objects when a field has an explicit write target. Closes #4649
This commit is contained in:
@@ -32,6 +32,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.bson.BsonRegularExpression;
|
||||
import org.bson.BsonValue;
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
@@ -868,7 +869,7 @@ public class QueryMapper {
|
||||
* conversions. In case of a {@link Collection} (used eg. for {@code $in} queries) the individual values will be
|
||||
* converted one by one.
|
||||
*
|
||||
* @param documentField the field and its meta data
|
||||
* @param documentField the field and its metadata
|
||||
* @param value the actual value. Can be {@literal null}.
|
||||
* @return the potentially converted target value.
|
||||
*/
|
||||
@@ -876,7 +877,8 @@ public class QueryMapper {
|
||||
private Object applyFieldTargetTypeHintToValue(Field documentField, @Nullable Object value) {
|
||||
|
||||
if (value == null || documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget()
|
||||
|| value instanceof Document || value instanceof DBObject) {
|
||||
|| value instanceof Document || value instanceof DBObject || value instanceof Pattern
|
||||
|| value instanceof BsonRegularExpression) {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,12 +29,15 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bson.BsonRegularExpression;
|
||||
import org.bson.conversions.Bson;
|
||||
import org.bson.types.Code;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
@@ -52,8 +55,17 @@ import org.springframework.data.mongodb.core.aggregation.EvaluationOperators.Exp
|
||||
import org.springframework.data.mongodb.core.aggregation.TypeBasedAggregationOperationContext;
|
||||
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
|
||||
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
|
||||
import org.springframework.data.mongodb.core.mapping.*;
|
||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.data.mongodb.core.mapping.DocumentReference;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
import org.springframework.data.mongodb.core.mapping.FieldName.Type;
|
||||
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;
|
||||
import org.springframework.data.mongodb.core.mapping.Unwrapped;
|
||||
import org.springframework.data.mongodb.core.query.BasicQuery;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
@@ -629,7 +641,7 @@ public class QueryMapperUnitTests {
|
||||
|
||||
org.bson.Document queryObject = query(
|
||||
where("referenceList").is(new org.bson.Document("$nested", new org.bson.Document("$keys", 0L))))
|
||||
.getQueryObject();
|
||||
.getQueryObject();
|
||||
|
||||
org.bson.Document mappedObject = mapper.getMappedObject(queryObject,
|
||||
context.getPersistentEntity(WithDBRefList.class));
|
||||
@@ -901,7 +913,7 @@ public class QueryMapperUnitTests {
|
||||
@Test // GH-3688
|
||||
void mappingShouldAllowSettingEntireNestedNumericKeyedMapValue() {
|
||||
|
||||
Query query = query(where("outerMap.1.map").is(null)); //newEntityWithComplexValueTypeMap()
|
||||
Query query = query(where("outerMap.1.map").is(null)); // newEntityWithComplexValueTypeMap()
|
||||
|
||||
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
|
||||
context.getPersistentEntity(EntityWithIntKeyedMapOfMap.class));
|
||||
@@ -1073,6 +1085,22 @@ public class QueryMapperUnitTests {
|
||||
assertThat(document).isEqualTo(new org.bson.Document("scripts", new Code(script)));
|
||||
}
|
||||
|
||||
@Test // GH-4649
|
||||
void shouldRetainRegexPattern() {
|
||||
|
||||
Query query = new Query(where("text").regex("foo"));
|
||||
|
||||
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
|
||||
context.getPersistentEntity(WithExplicitTargetTypes.class));
|
||||
|
||||
assertThat(document.get("text")).isInstanceOf(Pattern.class);
|
||||
|
||||
query = new Query(where("text").regex(new BsonRegularExpression("foo")));
|
||||
document = mapper.getMappedObject(query.getQueryObject(),
|
||||
context.getPersistentEntity(WithExplicitTargetTypes.class));
|
||||
assertThat(document.get("text")).isInstanceOf(BsonRegularExpression.class);
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-2339
|
||||
void findByIdUsesMappedIdFieldNameWithUnderscoreCorrectly() {
|
||||
|
||||
@@ -1376,7 +1404,8 @@ public class QueryMapperUnitTests {
|
||||
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
|
||||
context.getPersistentEntity(WithPropertyUsingUnderscoreInName.class));
|
||||
|
||||
assertThat(document).isEqualTo(new org.bson.Document("fieldname_with_underscores", new org.bson.Document("$exists", true)));
|
||||
assertThat(document)
|
||||
.isEqualTo(new org.bson.Document("fieldname_with_underscores", new org.bson.Document("$exists", true)));
|
||||
}
|
||||
|
||||
@Test // GH-3601
|
||||
@@ -1398,7 +1427,8 @@ public class QueryMapperUnitTests {
|
||||
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
|
||||
context.getPersistentEntity(WrapperAroundWithPropertyUsingUnderscoreInName.class));
|
||||
|
||||
assertThat(document).isEqualTo(new org.bson.Document("simple.fieldname_with_underscores", new org.bson.Document("$exists", true)));
|
||||
assertThat(document)
|
||||
.isEqualTo(new org.bson.Document("simple.fieldname_with_underscores", new org.bson.Document("$exists", true)));
|
||||
}
|
||||
|
||||
@Test // GH-3601
|
||||
@@ -1420,7 +1450,8 @@ public class QueryMapperUnitTests {
|
||||
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
|
||||
context.getPersistentEntity(WrapperAroundWithPropertyUsingUnderscoreInName.class));
|
||||
|
||||
assertThat(document).isEqualTo(new org.bson.Document("double_underscore.fieldname_with_underscores", new org.bson.Document("$exists", true)));
|
||||
assertThat(document).isEqualTo(
|
||||
new org.bson.Document("double_underscore.fieldname_with_underscores", new org.bson.Document("$exists", true)));
|
||||
}
|
||||
|
||||
@Test // GH-3601
|
||||
@@ -1431,7 +1462,8 @@ public class QueryMapperUnitTests {
|
||||
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
|
||||
context.getPersistentEntity(WrapperAroundWithPropertyUsingUnderscoreInName.class));
|
||||
|
||||
assertThat(document).isEqualTo(new org.bson.Document("double_underscore.renamed", new org.bson.Document("$exists", true)));
|
||||
assertThat(document)
|
||||
.isEqualTo(new org.bson.Document("double_underscore.renamed", new org.bson.Document("$exists", true)));
|
||||
}
|
||||
|
||||
@Test // GH-3633
|
||||
@@ -1469,7 +1501,8 @@ public class QueryMapperUnitTests {
|
||||
|
||||
Query query = query(where("address.street").is("1007 Mountain Drive"));
|
||||
|
||||
MongoCustomConversions mongoCustomConversions = new MongoCustomConversions(Collections.singletonList(new MyAddressToDocumentConverter()));
|
||||
MongoCustomConversions mongoCustomConversions = new MongoCustomConversions(
|
||||
Collections.singletonList(new MyAddressToDocumentConverter()));
|
||||
|
||||
this.context = new MongoMappingContext();
|
||||
this.context.setSimpleTypeHolder(mongoCustomConversions.getSimpleTypeHolder());
|
||||
@@ -1481,7 +1514,8 @@ public class QueryMapperUnitTests {
|
||||
|
||||
this.mapper = new QueryMapper(converter);
|
||||
|
||||
assertThat(mapper.getMappedSort(query.getQueryObject(), context.getPersistentEntity(Customer.class))).isEqualTo(new org.bson.Document("address.street", "1007 Mountain Drive"));
|
||||
assertThat(mapper.getMappedSort(query.getQueryObject(), context.getPersistentEntity(Customer.class)))
|
||||
.isEqualTo(new org.bson.Document("address.street", "1007 Mountain Drive"));
|
||||
}
|
||||
|
||||
@Test // GH-3790
|
||||
@@ -1502,7 +1536,8 @@ public class QueryMapperUnitTests {
|
||||
@Test // GH-3668
|
||||
void mapStringIdFieldProjection() {
|
||||
|
||||
org.bson.Document mappedFields = mapper.getMappedFields(new org.bson.Document("id", 1), context.getPersistentEntity(WithStringId.class));
|
||||
org.bson.Document mappedFields = mapper.getMappedFields(new org.bson.Document("id", 1),
|
||||
context.getPersistentEntity(WithStringId.class));
|
||||
assertThat(mappedFields).containsEntry("_id", 1);
|
||||
}
|
||||
|
||||
@@ -1528,7 +1563,8 @@ public class QueryMapperUnitTests {
|
||||
@Test // GH-3596
|
||||
void considersValueConverterWhenPresent() {
|
||||
|
||||
org.bson.Document mappedObject = mapper.getMappedObject(new org.bson.Document("text", "value"), context.getPersistentEntity(WithPropertyValueConverter.class));
|
||||
org.bson.Document mappedObject = mapper.getMappedObject(new org.bson.Document("text", "value"),
|
||||
context.getPersistentEntity(WithPropertyValueConverter.class));
|
||||
assertThat(mappedObject).isEqualTo(new org.bson.Document("text", "eulav"));
|
||||
}
|
||||
|
||||
@@ -1589,7 +1625,8 @@ public class QueryMapperUnitTests {
|
||||
@Test // GH-4464
|
||||
void usesKeyNameWithDotsIfFieldNameTypeIsKey() {
|
||||
|
||||
org.bson.Document mappedObject = mapper.getMappedObject(query(where("value").is("A")).getQueryObject(), context.getPersistentEntity(WithPropertyHavingDotsInFieldName.class));
|
||||
org.bson.Document mappedObject = mapper.getMappedObject(query(where("value").is("A")).getQueryObject(),
|
||||
context.getPersistentEntity(WithPropertyHavingDotsInFieldName.class));
|
||||
assertThat(mappedObject).isEqualTo("{ 'field.name.with.dots' : 'A' }");
|
||||
}
|
||||
|
||||
@@ -1606,7 +1643,8 @@ public class QueryMapperUnitTests {
|
||||
@Test // GH-4510
|
||||
void convertsNestedOperatorValueForPropertyThatHasValueConverter() {
|
||||
|
||||
org.bson.Document mappedObject = mapper.getMappedObject(query(where("text").gt("spring").lt( "data")).getQueryObject(),
|
||||
org.bson.Document mappedObject = mapper.getMappedObject(
|
||||
query(where("text").gt("spring").lt("data")).getQueryObject(),
|
||||
context.getPersistentEntity(WithPropertyValueConverter.class));
|
||||
|
||||
assertThat(mappedObject).isEqualTo("{ 'text' : { $gt : 'gnirps', $lt : 'atad' } }");
|
||||
@@ -1615,7 +1653,8 @@ public class QueryMapperUnitTests {
|
||||
@Test // GH-4510
|
||||
void convertsNestedOperatorValueForPropertyContainingListThatHasValueConverter() {
|
||||
|
||||
org.bson.Document mappedObject = mapper.getMappedObject(query(where("text").gt("spring").in( "data")).getQueryObject(),
|
||||
org.bson.Document mappedObject = mapper.getMappedObject(
|
||||
query(where("text").gt("spring").in("data")).getQueryObject(),
|
||||
context.getPersistentEntity(WithPropertyValueConverter.class));
|
||||
|
||||
assertThat(mappedObject).isEqualTo("{ 'text' : { $gt : 'gnirps', $in : [ 'atad' ] } }");
|
||||
@@ -1752,23 +1791,20 @@ public class QueryMapperUnitTests {
|
||||
|
||||
private String name;
|
||||
|
||||
@DocumentReference(lookup = "{ 'name' : ?#{#target} }")
|
||||
private Customer customer;
|
||||
@DocumentReference(lookup = "{ 'name' : ?#{#target} }") private Customer customer;
|
||||
|
||||
@DocumentReference(lookup = "{ 'name' : ?#{#target} }")
|
||||
private List<Customer> customers;
|
||||
@DocumentReference(lookup = "{ 'name' : ?#{#target} }") private List<Customer> customers;
|
||||
|
||||
@DocumentReference
|
||||
private Sample sample;
|
||||
@DocumentReference private Sample sample;
|
||||
|
||||
@DocumentReference
|
||||
private List<Sample> samples;
|
||||
@DocumentReference private List<Sample> samples;
|
||||
}
|
||||
|
||||
class WithTextScoreProperty {
|
||||
|
||||
@Id String id;
|
||||
@TextScore @Field("score") Float textScore;
|
||||
@TextScore
|
||||
@Field("score") Float textScore;
|
||||
}
|
||||
|
||||
static class RootForClassWithExplicitlyRenamedIdField {
|
||||
@@ -1805,7 +1841,7 @@ public class QueryMapperUnitTests {
|
||||
Map<Integer, SimpleEntityWithoutId> map;
|
||||
}
|
||||
|
||||
static class EntityWithIntKeyedMapOfMap{
|
||||
static class EntityWithIntKeyedMapOfMap {
|
||||
Map<Integer, EntityWithComplexValueTypeMap> outerMap;
|
||||
}
|
||||
|
||||
@@ -1818,6 +1854,9 @@ public class QueryMapperUnitTests {
|
||||
@Field(targetType = FieldType.SCRIPT) //
|
||||
String script;
|
||||
|
||||
@Field(targetType = FieldType.STRING) //
|
||||
String text;
|
||||
|
||||
@Field(targetType = FieldType.SCRIPT) //
|
||||
List<String> scripts;
|
||||
}
|
||||
@@ -1887,15 +1926,13 @@ public class QueryMapperUnitTests {
|
||||
|
||||
String fieldname_with_underscores;
|
||||
|
||||
@Field("renamed")
|
||||
String renamed_fieldname_with_underscores;
|
||||
@Field("renamed") String renamed_fieldname_with_underscores;
|
||||
}
|
||||
|
||||
@Document
|
||||
static class Customer {
|
||||
|
||||
@Id
|
||||
private ObjectId id;
|
||||
@Id private ObjectId id;
|
||||
private String name;
|
||||
private MyAddress address;
|
||||
}
|
||||
@@ -1906,8 +1943,7 @@ public class QueryMapperUnitTests {
|
||||
|
||||
static class WithPropertyValueConverter {
|
||||
|
||||
@ValueConverter(ReversingValueConverter.class)
|
||||
String text;
|
||||
@ValueConverter(ReversingValueConverter.class) String text;
|
||||
}
|
||||
|
||||
@WritingConverter
|
||||
@@ -1923,8 +1959,7 @@ public class QueryMapperUnitTests {
|
||||
|
||||
static class WithPropertyHavingDotsInFieldName {
|
||||
|
||||
@Field(name = "field.name.with.dots", nameType = Type.KEY)
|
||||
String value;
|
||||
@Field(name = "field.name.with.dots", nameType = Type.KEY) String value;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user