Skip to content

Commit 27b80d5

Browse files
committed
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
1 parent 170bdfe commit 27b80d5

File tree

2 files changed

+54
-28
lines changed

2 files changed

+54
-28
lines changed

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import org.apache.commons.logging.Log;
2525
import org.apache.commons.logging.LogFactory;
26+
import org.bson.BsonRegularExpression;
2627
import org.bson.BsonValue;
2728
import org.bson.Document;
2829
import org.bson.conversions.Bson;
@@ -833,15 +834,16 @@ protected boolean isKeyword(String candidate) {
833834
* conversions. In case of a {@link Collection} (used eg. for {@code $in} queries) the individual values will be
834835
* converted one by one.
835836
*
836-
* @param documentField the field and its meta data
837+
* @param documentField the field and its metadata
837838
* @param value the actual value. Can be {@literal null}.
838839
* @return the potentially converted target value.
839840
*/
840841
@Nullable
841842
private Object applyFieldTargetTypeHintToValue(Field documentField, @Nullable Object value) {
842843

843844
if (value == null || documentField.getProperty() == null || !documentField.getProperty().hasExplicitWriteTarget()
844-
|| value instanceof Document || value instanceof DBObject) {
845+
|| value instanceof Document || value instanceof DBObject || value instanceof Pattern
846+
|| value instanceof BsonRegularExpression) {
845847
return value;
846848
}
847849

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

+50-26
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@
2929
import java.util.Map;
3030
import java.util.Optional;
3131
import java.util.TreeMap;
32+
import java.util.regex.Pattern;
3233

34+
import org.bson.BsonRegularExpression;
3335
import org.bson.conversions.Bson;
3436
import org.bson.types.Code;
3537
import org.bson.types.ObjectId;
3638
import org.junit.jupiter.api.BeforeEach;
3739
import org.junit.jupiter.api.Test;
40+
3841
import org.springframework.core.convert.converter.Converter;
3942
import org.springframework.data.annotation.Id;
4043
import org.springframework.data.annotation.Transient;
@@ -553,7 +556,7 @@ void queryMapperShouldNotTryToMapDBRefListPropertyIfNestedInsideDocumentWithinDo
553556

554557
org.bson.Document queryObject = query(
555558
where("referenceList").is(new org.bson.Document("$nested", new org.bson.Document("$keys", 0L))))
556-
.getQueryObject();
559+
.getQueryObject();
557560

558561
org.bson.Document mappedObject = mapper.getMappedObject(queryObject,
559562
context.getPersistentEntity(WithDBRefList.class));
@@ -825,7 +828,7 @@ void mappingShouldRetainNestedNumericMapKeys() {
825828
@Test // GH-3688
826829
void mappingShouldAllowSettingEntireNestedNumericKeyedMapValue() {
827830

828-
Query query = query(where("outerMap.1.map").is(null)); //newEntityWithComplexValueTypeMap()
831+
Query query = query(where("outerMap.1.map").is(null)); // newEntityWithComplexValueTypeMap()
829832

830833
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
831834
context.getPersistentEntity(EntityWithIntKeyedMapOfMap.class));
@@ -997,6 +1000,22 @@ void shouldConvertCollectionPropertyWithExplicitTargetType() {
9971000
assertThat(document).isEqualTo(new org.bson.Document("scripts", new Code(script)));
9981001
}
9991002

1003+
@Test // GH-4649
1004+
void shouldRetainRegexPattern() {
1005+
1006+
Query query = new Query(where("text").regex("foo"));
1007+
1008+
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
1009+
context.getPersistentEntity(WithExplicitTargetTypes.class));
1010+
1011+
assertThat(document.get("text")).isInstanceOf(Pattern.class);
1012+
1013+
query = new Query(where("text").regex(new BsonRegularExpression("foo")));
1014+
document = mapper.getMappedObject(query.getQueryObject(),
1015+
context.getPersistentEntity(WithExplicitTargetTypes.class));
1016+
assertThat(document.get("text")).isInstanceOf(BsonRegularExpression.class);
1017+
}
1018+
10001019
@Test // DATAMONGO-2339
10011020
void findByIdUsesMappedIdFieldNameWithUnderscoreCorrectly() {
10021021

@@ -1300,7 +1319,8 @@ void resolvesFieldnameWithUnderscoresCorrectly() {
13001319
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
13011320
context.getPersistentEntity(WithPropertyUsingUnderscoreInName.class));
13021321

1303-
assertThat(document).isEqualTo(new org.bson.Document("fieldname_with_underscores", new org.bson.Document("$exists", true)));
1322+
assertThat(document)
1323+
.isEqualTo(new org.bson.Document("fieldname_with_underscores", new org.bson.Document("$exists", true)));
13041324
}
13051325

13061326
@Test // GH-3601
@@ -1322,7 +1342,8 @@ void resolvesSimpleNestedFieldnameWithUnderscoresCorrectly() {
13221342
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
13231343
context.getPersistentEntity(WrapperAroundWithPropertyUsingUnderscoreInName.class));
13241344

1325-
assertThat(document).isEqualTo(new org.bson.Document("simple.fieldname_with_underscores", new org.bson.Document("$exists", true)));
1345+
assertThat(document)
1346+
.isEqualTo(new org.bson.Document("simple.fieldname_with_underscores", new org.bson.Document("$exists", true)));
13261347
}
13271348

13281349
@Test // GH-3601
@@ -1344,7 +1365,8 @@ void resolvesFieldNameWithUnderscoreOnNestedFieldnameWithUnderscoresCorrectly()
13441365
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
13451366
context.getPersistentEntity(WrapperAroundWithPropertyUsingUnderscoreInName.class));
13461367

1347-
assertThat(document).isEqualTo(new org.bson.Document("double_underscore.fieldname_with_underscores", new org.bson.Document("$exists", true)));
1368+
assertThat(document).isEqualTo(
1369+
new org.bson.Document("double_underscore.fieldname_with_underscores", new org.bson.Document("$exists", true)));
13481370
}
13491371

13501372
@Test // GH-3601
@@ -1355,7 +1377,8 @@ void resolvesFieldNameWithUnderscoreOnNestedMappedFieldnameWithUnderscoresCorrec
13551377
org.bson.Document document = mapper.getMappedObject(query.getQueryObject(),
13561378
context.getPersistentEntity(WrapperAroundWithPropertyUsingUnderscoreInName.class));
13571379

1358-
assertThat(document).isEqualTo(new org.bson.Document("double_underscore.renamed", new org.bson.Document("$exists", true)));
1380+
assertThat(document)
1381+
.isEqualTo(new org.bson.Document("double_underscore.renamed", new org.bson.Document("$exists", true)));
13591382
}
13601383

13611384
@Test // GH-3633
@@ -1393,7 +1416,8 @@ void allowsUsingFieldPathsForPropertiesHavingCustomConversionRegistered() {
13931416

13941417
Query query = query(where("address.street").is("1007 Mountain Drive"));
13951418

1396-
MongoCustomConversions mongoCustomConversions = new MongoCustomConversions(Collections.singletonList(new MyAddressToDocumentConverter()));
1419+
MongoCustomConversions mongoCustomConversions = new MongoCustomConversions(
1420+
Collections.singletonList(new MyAddressToDocumentConverter()));
13971421

13981422
this.context = new MongoMappingContext();
13991423
this.context.setSimpleTypeHolder(mongoCustomConversions.getSimpleTypeHolder());
@@ -1405,7 +1429,8 @@ void allowsUsingFieldPathsForPropertiesHavingCustomConversionRegistered() {
14051429

14061430
this.mapper = new QueryMapper(converter);
14071431

1408-
assertThat(mapper.getMappedSort(query.getQueryObject(), context.getPersistentEntity(Customer.class))).isEqualTo(new org.bson.Document("address.street", "1007 Mountain Drive"));
1432+
assertThat(mapper.getMappedSort(query.getQueryObject(), context.getPersistentEntity(Customer.class)))
1433+
.isEqualTo(new org.bson.Document("address.street", "1007 Mountain Drive"));
14091434
}
14101435

14111436
@Test // GH-3790
@@ -1426,7 +1451,8 @@ void shouldAcceptExprAsCriteriaDefinition() {
14261451
@Test // GH-3668
14271452
void mapStringIdFieldProjection() {
14281453

1429-
org.bson.Document mappedFields = mapper.getMappedFields(new org.bson.Document("id", 1), context.getPersistentEntity(WithStringId.class));
1454+
org.bson.Document mappedFields = mapper.getMappedFields(new org.bson.Document("id", 1),
1455+
context.getPersistentEntity(WithStringId.class));
14301456
assertThat(mappedFields).containsEntry("_id", 1);
14311457
}
14321458

@@ -1452,7 +1478,8 @@ void mapStringIdFieldProjection() {
14521478
@Test // GH-3596
14531479
void considersValueConverterWhenPresent() {
14541480

1455-
org.bson.Document mappedObject = mapper.getMappedObject(new org.bson.Document("text", "value"), context.getPersistentEntity(WithPropertyValueConverter.class));
1481+
org.bson.Document mappedObject = mapper.getMappedObject(new org.bson.Document("text", "value"),
1482+
context.getPersistentEntity(WithPropertyValueConverter.class));
14561483
assertThat(mappedObject).isEqualTo(new org.bson.Document("text", "eulav"));
14571484
}
14581485

@@ -1651,23 +1678,20 @@ static class WithDocumentReference {
16511678

16521679
private String name;
16531680

1654-
@DocumentReference(lookup = "{ 'name' : ?#{#target} }")
1655-
private Customer customer;
1681+
@DocumentReference(lookup = "{ 'name' : ?#{#target} }") private Customer customer;
16561682

1657-
@DocumentReference(lookup = "{ 'name' : ?#{#target} }")
1658-
private List<Customer> customers;
1683+
@DocumentReference(lookup = "{ 'name' : ?#{#target} }") private List<Customer> customers;
16591684

1660-
@DocumentReference
1661-
private Sample sample;
1685+
@DocumentReference private Sample sample;
16621686

1663-
@DocumentReference
1664-
private List<Sample> samples;
1687+
@DocumentReference private List<Sample> samples;
16651688
}
16661689

16671690
class WithTextScoreProperty {
16681691

16691692
@Id String id;
1670-
@TextScore @Field("score") Float textScore;
1693+
@TextScore
1694+
@Field("score") Float textScore;
16711695
}
16721696

16731697
static class RootForClassWithExplicitlyRenamedIdField {
@@ -1704,7 +1728,7 @@ static class EntityWithComplexValueTypeMap {
17041728
Map<Integer, SimpleEntityWithoutId> map;
17051729
}
17061730

1707-
static class EntityWithIntKeyedMapOfMap{
1731+
static class EntityWithIntKeyedMapOfMap {
17081732
Map<Integer, EntityWithComplexValueTypeMap> outerMap;
17091733
}
17101734

@@ -1717,6 +1741,9 @@ static class WithExplicitTargetTypes {
17171741
@Field(targetType = FieldType.SCRIPT) //
17181742
String script;
17191743

1744+
@Field(targetType = FieldType.STRING) //
1745+
String text;
1746+
17201747
@Field(targetType = FieldType.SCRIPT) //
17211748
List<String> scripts;
17221749
}
@@ -1786,15 +1813,13 @@ static class WithPropertyUsingUnderscoreInName {
17861813

17871814
String fieldname_with_underscores;
17881815

1789-
@Field("renamed")
1790-
String renamed_fieldname_with_underscores;
1816+
@Field("renamed") String renamed_fieldname_with_underscores;
17911817
}
17921818

17931819
@Document
17941820
static class Customer {
17951821

1796-
@Id
1797-
private ObjectId id;
1822+
@Id private ObjectId id;
17981823
private String name;
17991824
private MyAddress address;
18001825
}
@@ -1805,8 +1830,7 @@ static class MyAddress {
18051830

18061831
static class WithPropertyValueConverter {
18071832

1808-
@ValueConverter(ReversingValueConverter.class)
1809-
String text;
1833+
@ValueConverter(ReversingValueConverter.class) String text;
18101834
}
18111835

18121836
@WritingConverter

0 commit comments

Comments
 (0)