From d7107d49bf3511bc630a9301e997668a878a84b1 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 4 Jul 2019 10:14:44 +0200 Subject: [PATCH] DATAMONGO-2314 - Fix query by example on nested properties. This fix allows using alike on nested properties. new Criteria("nested").alike(Example.of(probe, matching().withIgnorePaths("_class")))); Switch tests to AssertJ. Original pull request: #771. --- .../mongodb/core/convert/QueryMapper.java | 11 +++- .../data/mongodb/core/query/Criteria.java | 1 - .../mongodb/core/QueryByExampleTests.java | 63 ++++++++++++------- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index ff7ce6ea5..e622057e1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -307,6 +307,10 @@ public class QueryMapper { Object convertedValue = needsAssociationConversion ? convertAssociation(value, property) : getMappedValue(property.with(keyword.getKey()), value); + if(keyword.isSample() && convertedValue instanceof Document) { + return (Document) convertedValue; + } + return new Document(keyword.key, convertedValue); } @@ -314,9 +318,8 @@ public class QueryMapper { * Returns the mapped value for the given source object assuming it's a value for the given * {@link MongoPersistentProperty}. * + * @param documentField the key the value will be bound to eventually * @param value the source object to be mapped - * @param property the property the value is a value for - * @param newKey the key the value will be bound to eventually * @return */ @Nullable @@ -423,6 +426,10 @@ public class QueryMapper { @SuppressWarnings("unchecked") protected Object convertSimpleOrDocument(Object source, @Nullable MongoPersistentEntity entity) { + if(source instanceof Example) { + return exampleMapper.getMappedExample((Example)source, entity); + } + if (source instanceof List) { return delegateConvertToMongoType(source, entity); } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java index 208a3a7b3..21f1b7345 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java @@ -597,7 +597,6 @@ public class Criteria implements CriteriaDefinition { public Criteria alike(Example sample) { criteria.put("$example", sample); - this.criteriaChain.add(this); return this; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java index 647f93a91..ae899d070 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java @@ -15,13 +15,11 @@ */ package org.springframework.data.mongodb.core; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; +import static org.assertj.core.api.Assertions.*; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.net.UnknownHostException; import java.util.List; import org.junit.Before; @@ -50,7 +48,7 @@ public class QueryByExampleTests { Person p1, p2, p3; @Before - public void setUp() throws UnknownHostException { + public void setUp() { operations = new MongoTemplate(new MongoClient(), "query-by-example"); operations.remove(new Query(), Person.class); @@ -82,8 +80,7 @@ public class QueryByExampleTests { Query query = new Query(new Criteria().alike(Example.of(sample))); List result = operations.find(query, Person.class); - assertThat(result, hasSize(2)); - assertThat(result, hasItems(p1, p3)); + assertThat(result).containsExactlyInAnyOrder(p1, p3); } @Test // DATAMONGO-1245 @@ -96,8 +93,7 @@ public class QueryByExampleTests { Query query = new Query(new Criteria().alike(Example.of(sample))); List result = operations.find(query, Person.class); - assertThat(result, hasSize(1)); - assertThat(result, hasItem(p3)); + assertThat(result).containsExactly(p3); } @Test // DATAMONGO-1245 @@ -112,8 +108,7 @@ public class QueryByExampleTests { Query query = new Query(new Criteria().alike(Example.of(sample))); List result = operations.find(query, Person.class); - assertThat(result, hasSize(1)); - assertThat(result, hasItem(p4)); + assertThat(result).containsExactly(p4); } @Test // DATAMONGO-1245 @@ -126,7 +121,7 @@ public class QueryByExampleTests { Query query = new Query(new Criteria().alike(Example.of(sample))); List result = operations.find(query, Person.class); - assertThat(result, is(empty())); + assertThat(result).isEmpty(); } @Test // DATAMONGO-1245 @@ -137,8 +132,7 @@ public class QueryByExampleTests { Query query = new Query(new Criteria().alike(Example.of(sample))); List result = operations.find(query, Person.class); - assertThat(result, hasSize(3)); - assertThat(result, hasItems(p1, p2, p3)); + assertThat(result).containsExactlyInAnyOrder(p1, p2, p3); } @Test // DATAMONGO-1245 @@ -150,7 +144,7 @@ public class QueryByExampleTests { Query query = new Query(new Criteria().alike(Example.of(sample)).and("firstname").regex("^ary*")); List result = operations.find(query, Person.class); - assertThat(result.size(), is(1)); + assertThat(result).hasSize(1); } @Test // DATAMONGO-1459 @@ -163,8 +157,7 @@ public class QueryByExampleTests { Query query = Query.query(Criteria.byExample(Example.of(probe, ExampleMatcher.matchingAny()))); List result = operations.find(query, Person.class); - assertThat(result, hasSize(2)); - assertThat(result, hasItems(p1, p2)); + assertThat(result).containsExactlyInAnyOrder(p1, p2); } @Test // DATAMONGO-1768 @@ -176,7 +169,7 @@ public class QueryByExampleTests { Query query = new Query(new Criteria().alike(Example.of(probe))); List result = operations.find(query, Person.class); - assertThat(result, hasSize(0)); + assertThat(result).isEmpty(); } @Test // DATAMONGO-1768 @@ -189,8 +182,7 @@ public class QueryByExampleTests { new Criteria().alike(Example.of(probe, ExampleMatcher.matching().withIgnorePaths("_class")))); List result = operations.find(query, Person.class); - assertThat(result, hasSize(2)); - assertThat(result, hasItems(p1, p3)); + assertThat(result).containsExactlyInAnyOrder(p1, p3); } @Test // DATAMONGO-1768 @@ -202,8 +194,28 @@ public class QueryByExampleTests { Query query = new Query(new Criteria().alike(Example.of(probe, UntypedExampleMatcher.matching()))); List result = operations.find(query, Person.class); - assertThat(result, hasSize(2)); - assertThat(result, hasItems(p1, p3)); + assertThat(result).containsExactlyInAnyOrder(p1, p3); + } + + @Test // DATAMONGO-2314 + public void alikeShouldWorkOnNestedProperties() { + + PersonWrapper source1 = new PersonWrapper(); + source1.id = "with-child-doc-1"; + source1.child = p1; + + PersonWrapper source2 = new PersonWrapper(); + source2.id = "with-child-doc-2"; + source2.child = p2; + + operations.save(source1); + operations.save(source2); + + Query query = new Query( + new Criteria("child").alike(Example.of(p1, ExampleMatcher.matching().withIgnorePaths("_class")))); + List result = operations.find(query, PersonWrapper.class); + + assertThat(result).containsExactly(source1); } @Document("dramatis-personae") @@ -223,4 +235,13 @@ public class QueryByExampleTests { String firstname, middlename; @Field("last_name") String lastname; } + + @Document("dramatis-personae") + @EqualsAndHashCode + @ToString + static class PersonWrapper { + + @Id String id; + Person child; + } }