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.
This commit is contained in:
committed by
Oliver Gierke
parent
1fd97713c1
commit
81f2c910f7
@@ -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;
|
||||
*
|
||||
* @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> {
|
||||
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> {
|
||||
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> {
|
||||
source = source + "$";
|
||||
break;
|
||||
case CONTAINING:
|
||||
case NOT_CONTAINING:
|
||||
source = "*" + source + "*";
|
||||
break;
|
||||
case SIMPLE_PROPERTY:
|
||||
|
||||
@@ -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 {
|
||||
@Field("foo") String username;
|
||||
|
||||
@DBRef User creator;
|
||||
|
||||
List<String> emailAddresses;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user