diff --git a/pom.xml b/pom.xml
index 3a9b4f5ad7..440481c7a6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1424-SNAPSHOT
pom
Spring Data MongoDB
diff --git a/spring-data-mongodb-cross-store/pom.xml b/spring-data-mongodb-cross-store/pom.xml
index 6554045e11..44ba44be83 100644
--- a/spring-data-mongodb-cross-store/pom.xml
+++ b/spring-data-mongodb-cross-store/pom.xml
@@ -6,7 +6,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1424-SNAPSHOT
../pom.xml
@@ -48,7 +48,7 @@
org.springframework.data
spring-data-mongodb
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1424-SNAPSHOT
diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml
index 2d02722262..08ce7695e4 100644
--- a/spring-data-mongodb-distribution/pom.xml
+++ b/spring-data-mongodb-distribution/pom.xml
@@ -13,7 +13,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1424-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb-log4j/pom.xml b/spring-data-mongodb-log4j/pom.xml
index ee5e3336db..474aa28ff1 100644
--- a/spring-data-mongodb-log4j/pom.xml
+++ b/spring-data-mongodb-log4j/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1424-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index edfa519fad..6667b6ba27 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -11,7 +11,7 @@
org.springframework.data
spring-data-mongodb-parent
- 1.10.0.BUILD-SNAPSHOT
+ 1.10.0.DATAMONGO-1424-SNAPSHOT
../pom.xml
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java
index a1d85dff99..f3298a8af4 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/MongoRegexCreator.java
@@ -72,7 +72,7 @@ private String prepareAndEscapeStringBeforeApplyingLikeRegex(String source, Type
return source;
}
- if (!ObjectUtils.nullSafeEquals(Type.LIKE, type)) {
+ if (!ObjectUtils.nullSafeEquals(Type.LIKE, type) && !ObjectUtils.nullSafeEquals(Type.NOT_LIKE, type)) {
return PUNCTATION_PATTERN.matcher(source).find() ? Pattern.quote(source) : source;
}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java
index 083b778d7e..13170e1579 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2015 the original author or authors.
+ * Copyright 2010-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -199,6 +199,8 @@ private Criteria from(Part part, MongoPersistentProperty property, Criteria crit
case ENDING_WITH:
case CONTAINING:
return createContainingCriteria(part, property, criteria, parameters);
+ case NOT_LIKE:
+ return createContainingCriteria(part, property, criteria.not(), parameters);
case NOT_CONTAINING:
return createContainingCriteria(part, property, criteria, parameters).not();
case REGEX:
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java
index b924d81883..f34c37d821 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java
@@ -1261,4 +1261,14 @@ public void findAllByExampleShouldResolveStuffCorrectly() {
assertThat(result.size(), is(2));
}
+ /**
+ * @see DATAMONGO-1424
+ */
+ @Test
+ public void findsPersonsByFirstnameNotLike() throws Exception {
+
+ List result = repository.findByFirstnameNotLike("Bo*");
+ assertThat(result.size(), is((int) (repository.count() - 1)));
+ assertThat(result, not(hasItem(boyd)));
+ }
}
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java
index eae2c02e10..061b5ac9c1 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2015 the original author or authors.
+ * Copyright 2010-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -89,6 +89,14 @@ public interface PersonRepository extends MongoRepository, Query
*/
List findByFirstnameLike(String firstname);
+ /**
+ * Returns all {@link Person}s with a firstname not matching the given one (*-wildcard supported).
+ *
+ * @param firstname
+ * @return
+ */
+ List findByFirstnameNotLike(String firstname);
+
List findByFirstnameLikeOrderByLastnameAsc(String firstname, Sort sort);
@Query("{'age' : { '$lt' : ?0 } }")
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java
index 9780f32be9..a1d1c08fc3 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2015 the original author or authors.
+ * Copyright 2011-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -668,6 +668,62 @@ public void bindsNullValueToContainsClause() {
assertThat(query, is(query(where("emailAddresses").in((Object) null))));
}
+ /**
+ * @see DATAMONGO-1424
+ */
+ @Test
+ public void notLikeShouldEscapeSourceWhenUsedWithLeadingAndTrailingWildcard() {
+
+ PartTree tree = new PartTree("findByUsernameNotLike", User.class);
+ ConvertingParameterAccessor accessor = getAccessor(converter, "*fire.fight+*");
+
+ Query query = new MongoQueryCreator(tree, accessor, context).createQuery();
+
+ assertThat(query.getQueryObject(),
+ is(query(where("username").not().regex(".*\\Qfire.fight+\\E.*")).getQueryObject()));
+ }
+
+ /**
+ * @see DATAMONGO-1424
+ */
+ @Test
+ public void notLikeShouldEscapeSourceWhenUsedWithLeadingWildcard() {
+
+ PartTree tree = new PartTree("findByUsernameNotLike", User.class);
+ ConvertingParameterAccessor accessor = getAccessor(converter, "*steel.heart+");
+
+ Query query = new MongoQueryCreator(tree, accessor, context).createQuery();
+
+ assertThat(query.getQueryObject(),
+ is(query(where("username").not().regex(".*\\Qsteel.heart+\\E")).getQueryObject()));
+ }
+
+ /**
+ * @see DATAMONGO-1424
+ */
+ @Test
+ public void notLikeShouldEscapeSourceWhenUsedWithTrailingWildcard() {
+
+ PartTree tree = new PartTree("findByUsernameNotLike", User.class);
+ MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "cala.mity+*"), context);
+ Query query = creator.createQuery();
+
+ assertThat(query.getQueryObject(), is(query(where("username").not().regex("\\Qcala.mity+\\E.*")).getQueryObject()));
+ }
+
+ /**
+ * @see DATAMONGO-1424
+ */
+ @Test
+ public void notLikeShouldBeTreatedCorrectlyWhenUsedWithWildcardOnly() {
+
+ PartTree tree = new PartTree("findByUsernameNotLike", User.class);
+ ConvertingParameterAccessor accessor = getAccessor(converter, "*");
+
+ Query query = new MongoQueryCreator(tree, accessor, context).createQuery();
+ assertThat(query.getQueryObject(), is(query(where("username").not().regex(".*")).getQueryObject()));
+ }
+
interface PersonRepository extends Repository {
List findByLocationNearAndFirstname(Point location, Distance maxDistance, String firstname);
diff --git a/src/main/asciidoc/reference/mongo-repositories.adoc b/src/main/asciidoc/reference/mongo-repositories.adoc
index d78880fcff..1ceadd7afd 100644
--- a/src/main/asciidoc/reference/mongo-repositories.adoc
+++ b/src/main/asciidoc/reference/mongo-repositories.adoc
@@ -208,6 +208,10 @@ NOTE: Note that for version 1.0 we currently don't support referring to paramete
| `findByFirstnameLike(String name)`
| `{"firstname" : name} ( name as regex)`
+| `NotLike`, `IsNotLike`, `EndingWith`
+| `findByFirstnameNotLike(String name)`
+| `{"firstname" : { "$not" : name }} ( name as regex)`
+
| `Containing` on String
| `findByFirstnameContaining(String name)`
| `{"firstname" : name} (name as regex)`