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.

Original pull request: #241.
This commit is contained in:
Christoph Strobl
2014-11-11 12:49:56 +01:00
committed by Oliver Gierke
parent c04343a764
commit 3349454a51
2 changed files with 40 additions and 2 deletions

View File

@@ -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> {
@@ -198,7 +199,7 @@ 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 REGEX:
return criteria.regex(parameters.next().toString());
case EXISTS:
@@ -292,6 +293,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.
*

View File

@@ -438,6 +438,20 @@ 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"))));
}
interface PersonRepository extends Repository<Person, Long> {
List<Person> findByLocationNearAndFirstname(Point location, Distance maxDistance, String firstname);
@@ -448,5 +462,7 @@ public class MongoQueryCreatorUnitTests {
@Field("foo") String username;
@DBRef User creator;
List<String> emailAddresses;
}
}