Browse Source

DATAMONGO-1075 - Containing keyword is now correctly translated for collection properties.

We now inspect the properties type when creating criteria for CONTAINS keyword so that, if the target property is of type String, we use an expression, and if the property is collection like we try to finds an exact match within the collection using $in.

Added support for NotContaining along the way.

Original pull request: #241.
pull/241/merge
Christoph Strobl 11 years ago committed by Oliver Gierke
parent
commit
81f2c910f7
  1. 29
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java
  2. 43
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java

29
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/MongoQueryCreator.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 the original author or authors.
* Copyright 2010-2014 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.
@ -46,6 +46,7 @@ import org.springframework.util.Assert; @@ -46,6 +46,7 @@ import org.springframework.util.Assert;
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
*/
class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
@ -190,7 +191,9 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> { @@ -190,7 +191,9 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
case STARTING_WITH:
case ENDING_WITH:
case CONTAINING:
return addAppropriateLikeRegexTo(criteria, part, parameters.next().toString());
return createContainingCriteria(part, property, criteria, parameters);
case NOT_CONTAINING:
return createContainingCriteria(part, property, criteria, parameters).not();
case REGEX:
return criteria.regex(parameters.next().toString());
case EXISTS:
@ -284,6 +287,27 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> { @@ -284,6 +287,27 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
Arrays.asList(IgnoreCaseType.ALWAYS, IgnoreCaseType.WHEN_POSSIBLE), part.shouldIgnoreCase()));
}
/**
* If the target property of the comparison is of type String, then the operator checks for match using regular
* expression. If the target property of the comparison is a {@link Collection} then the operator evaluates to true if
* it finds an exact match within any member of the {@link Collection}.
*
* @param part
* @param property
* @param criteria
* @param parameters
* @return
*/
private Criteria createContainingCriteria(Part part, MongoPersistentProperty property, Criteria criteria,
PotentiallyConvertingIterator parameters) {
if (property.isCollectionLike()) {
return criteria.in(nextAsArray(parameters, property));
}
return addAppropriateLikeRegexTo(criteria, part, parameters.next().toString());
}
/**
* Creates an appropriate like-regex and appends it to the given criteria.
*
@ -357,6 +381,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> { @@ -357,6 +381,7 @@ class MongoQueryCreator extends AbstractQueryCreator<Query, Criteria> {
source = source + "$";
break;
case CONTAINING:
case NOT_CONTAINING:
source = "*" + source + "*";
break;
case SIMPLE_PROPERTY:

43
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java

@ -425,6 +425,47 @@ public class MongoQueryCreatorUnitTests { @@ -425,6 +425,47 @@ public class MongoQueryCreatorUnitTests {
assertThat(query, is(query(where("firstName").regex("^dave$", "i").and("age").is(42))));
}
/**
* @see DATAMONGO-1075
*/
@Test
public void shouldCreateInClauseWhenUsingContainsOnCollectionLikeProperty() {
PartTree tree = new PartTree("findByEmailAddressesContaining", User.class);
MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave"), context);
Query query = creator.createQuery();
assertThat(query, is(query(where("emailAddresses").in("dave"))));
}
/**
* @see DATAMONGO-1075
*/
@Test
public void shouldCreateInClauseWhenUsingNotContainsOnCollectionLikeProperty() {
PartTree tree = new PartTree("findByEmailAddressesNotContaining", User.class);
MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "dave"), context);
Query query = creator.createQuery();
assertThat(query, is(query(where("emailAddresses").not().in("dave"))));
}
/**
* @see DATAMONGO-1075
*/
@Test
public void shouldCreateRegexWhenUsingNotContainsOnStringProperty() {
PartTree tree = new PartTree("findByUsernameNotContaining", User.class);
MongoQueryCreator creator = new MongoQueryCreator(tree, getAccessor(converter, "thew"), context);
Query query = creator.createQuery();
assertThat(query, is(query(where("username").regex(".*thew.*").not())));
}
interface PersonRepository extends Repository<Person, Long> {
List<Person> findByLocationNearAndFirstname(Point location, Distance maxDistance, String firstname);
@ -435,5 +476,7 @@ public class MongoQueryCreatorUnitTests { @@ -435,5 +476,7 @@ public class MongoQueryCreatorUnitTests {
@Field("foo") String username;
@DBRef User creator;
List<String> emailAddresses;
}
}

Loading…
Cancel
Save