From 3349454a515de760cd9e7df5843673fe4676c497 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Tue, 11 Nov 2014 12:49:56 +0100 Subject: [PATCH] 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. --- .../repository/query/MongoQueryCreator.java | 26 +++++++++++++++++-- .../query/MongoQueryCreatorUnitTests.java | 16 ++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) 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 4a687de36..c4dd1ccc7 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-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 { @@ -198,7 +199,7 @@ class MongoQueryCreator extends AbstractQueryCreator { 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 { 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. * 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 2e1767eac..b67664944 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 @@ -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 { List findByLocationNearAndFirstname(Point location, Distance maxDistance, String firstname); @@ -448,5 +462,7 @@ public class MongoQueryCreatorUnitTests { @Field("foo") String username; @DBRef User creator; + + List emailAddresses; } }