From c47bd4cbe53e93c06f9b9f1e79c5bf4240b0c046 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 31 Jul 2019 10:43:01 +0200 Subject: [PATCH 1/3] DATAMONGO-2327 - Prepare issue branch. --- pom.xml | 2 +- spring-data-mongodb-benchmarks/pom.xml | 2 +- spring-data-mongodb-distribution/pom.xml | 2 +- spring-data-mongodb/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 08da7a4466..ab7c703223 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 2.2.0.BUILD-SNAPSHOT + 2.2.0.DATAMONGO-2327-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index bb7d9f03cc..5dedf6b5c8 100644 --- a/spring-data-mongodb-benchmarks/pom.xml +++ b/spring-data-mongodb-benchmarks/pom.xml @@ -7,7 +7,7 @@ org.springframework.data spring-data-mongodb-parent - 2.2.0.BUILD-SNAPSHOT + 2.2.0.DATAMONGO-2327-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index ae8b9fdb30..2d27f0b4b8 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -14,7 +14,7 @@ org.springframework.data spring-data-mongodb-parent - 2.2.0.BUILD-SNAPSHOT + 2.2.0.DATAMONGO-2327-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index b611cf01a8..015123b5e0 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 2.2.0.BUILD-SNAPSHOT + 2.2.0.DATAMONGO-2327-SNAPSHOT ../pom.xml From 6dd1e2f2ee744f56c00385a250ee5557226d3544 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 31 Jul 2019 11:59:03 +0200 Subject: [PATCH 2/3] DATAMONGO-2327 - Add toJson method to Querydsl query support. This allows to obtain the raw Json representation of the query for eg. debug usage. We also updated the toString method to return a full Mongo Shell compatible representation of the query including projections, order, skip and limit. --- .../support/QuerydslAbstractMongodbQuery.java | 64 ++++++++++++++++++- .../QuerydslRepositorySupportTests.java | 29 ++++++++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java index e9a3ad9e65..8a23f2f9d1 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java @@ -18,6 +18,8 @@ import java.util.List; import org.bson.Document; +import org.bson.json.JsonMode; +import org.bson.json.JsonWriterSettings; import org.springframework.lang.Nullable; import com.querydsl.core.DefaultQueryMetadata; @@ -48,6 +50,9 @@ public abstract class QuerydslAbstractMongodbQuery> implements SimpleQuery { + private static final JsonWriterSettings JSON_WRITER_SETTINGS = JsonWriterSettings.builder().outputMode(JsonMode.SHELL) + .build(); + private final MongodbDocumentSerializer serializer; private final QueryMixin queryMixin; @@ -195,8 +200,65 @@ Document asDocument() { return createQuery(queryMixin.getMetadata().getWhere()); } + /** + * Returns the {@literal Mongo Shell} representation of the query.
+ * The following query + * + *
+	 *
+	 * where(p.lastname.eq("Matthews")).orderBy(p.firstname.asc()).offset(1).limit(5);
+	 * 
+ * + * results in + * + *
+	 *
+	 * find({"lastname" : "Matthews"}).sort({"firstname" : 1}).skip(1).limit(5)
+	 * 
+ * + * @return never {@literal null}. + */ @Override public String toString() { - return asDocument().toString(); + + Document projection = createProjection(queryMixin.getMetadata().getProjection()); + Document sort = createSort(queryMixin.getMetadata().getOrderBy()); + + StringBuilder sb = new StringBuilder("find(" + asDocument().toJson(JSON_WRITER_SETTINGS)); + if (!projection.isEmpty()) { + sb.append(", " + projection.toJson(JSON_WRITER_SETTINGS)); + } + sb.append(")"); + if (!sort.isEmpty()) { + sb.append(".sort(" + sort.toJson(JSON_WRITER_SETTINGS) + ")"); + } + if (queryMixin.getMetadata().getModifiers().getOffset() != null) { + sb.append(".skip(" + queryMixin.getMetadata().getModifiers().getOffset() + ")"); + } + if (queryMixin.getMetadata().getModifiers().getLimit() != null) { + sb.append(".limit(" + queryMixin.getMetadata().getModifiers().getLimit() + ")"); + } + return sb.toString(); + } + + /** + * Obtain the {@literal Mongo Shell} json query representation. + * + * @return never {@literal null}. + * @since 2.2 + */ + public String toJson() { + return toJson(JSON_WRITER_SETTINGS); + } + + /** + * Obtain the json query representation applying given {@link JsonWriterSettings settings}. + * + * @param settings must not be {@literal null}. + * @return never {@literal null}. + * @since 2.2 + */ + public String toJson(JsonWriterSettings settings) { + return asDocument().toJson(settings); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java index b36084729d..daa847c259 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java @@ -25,7 +25,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; - import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.annotation.Id; @@ -39,6 +38,7 @@ import org.springframework.data.mongodb.repository.User; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.StringUtils; /** * Unit tests for {@link QuerydslRepositorySupport}. @@ -248,6 +248,33 @@ public void shouldUseStringForValidObjectIdHexStrings() { assertThat(inQuery.fetchOne()).isEqualTo(document); } + @Test // DATAMONGO-2327 + public void toJsonShouldRenderQuery() { + + QPerson p = QPerson.person; + SpringDataMongodbQuery query = repoSupport.from(p).where(p.lastname.eq("Matthews")) + .orderBy(p.firstname.asc()).offset(1).limit(5); + + assertThat(StringUtils.trimAllWhitespace(query.toJson())).isEqualTo("{\"lastname\":\"Matthews\"}"); + } + + @Test // DATAMONGO-2327 + public void toStringShouldRenderQuery() { + + QPerson p = QPerson.person; + SpringDataMongodbQuery query = repoSupport.from(p).where(p.lastname.eq("Matthews")); + + assertThat(StringUtils.trimAllWhitespace(query.toString())).isEqualTo("find({\"lastname\":\"Matthews\"})"); + + query = query.orderBy(p.firstname.asc()); + assertThat(StringUtils.trimAllWhitespace(query.toString())) + .isEqualTo("find({\"lastname\":\"Matthews\"}).sort({\"firstname\":1})"); + + query = query.offset(1).limit(5); + assertThat(StringUtils.trimAllWhitespace(query.toString())) + .isEqualTo("find({\"lastname\":\"Matthews\"}).sort({\"firstname\":1}).skip(1).limit(5)"); + } + @Data @Document public static class Outer { From 657bdb89a1bbd104c79f568ddf51fb236695f1f6 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 1 Aug 2019 14:09:02 +0200 Subject: [PATCH 3/3] DATAMONGO-2327 - Polishing. Add support for DBRef encoding. Update Javadoc. --- .../support/QuerydslAbstractMongodbQuery.java | 23 ++++++++++++------- .../QuerydslRepositorySupportTests.java | 15 ++++++++---- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java index 8a23f2f9d1..6020077aef 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/QuerydslAbstractMongodbQuery.java @@ -18,10 +18,13 @@ import java.util.List; import org.bson.Document; +import org.bson.codecs.DocumentCodec; import org.bson.json.JsonMode; import org.bson.json.JsonWriterSettings; + import org.springframework.lang.Nullable; +import com.mongodb.MongoClientSettings; import com.querydsl.core.DefaultQueryMetadata; import com.querydsl.core.QueryModifiers; import com.querydsl.core.SimpleQuery; @@ -40,7 +43,7 @@ * 2.0. *

* Modified for usage with {@link MongodbDocumentSerializer}. - * + * * @param concrete subtype * @author laimw * @author Mark Paluch @@ -184,7 +187,7 @@ protected Document createSort(List> orderSpecifiers) { /** * Get the actual {@link QueryMixin} delegate. - * + * * @return */ QueryMixin getQueryMixin() { @@ -216,6 +219,9 @@ Document asDocument() { * find({"lastname" : "Matthews"}).sort({"firstname" : 1}).skip(1).limit(5) * * + * Note that encoding to {@link String} may fail when using data types that cannot be encoded or DBRef's without an + * identifier. + * * @return never {@literal null}. */ @Override @@ -223,27 +229,28 @@ public String toString() { Document projection = createProjection(queryMixin.getMetadata().getProjection()); Document sort = createSort(queryMixin.getMetadata().getOrderBy()); + DocumentCodec codec = new DocumentCodec(MongoClientSettings.getDefaultCodecRegistry()); - StringBuilder sb = new StringBuilder("find(" + asDocument().toJson(JSON_WRITER_SETTINGS)); + StringBuilder sb = new StringBuilder("find(" + asDocument().toJson(JSON_WRITER_SETTINGS, codec)); if (!projection.isEmpty()) { - sb.append(", " + projection.toJson(JSON_WRITER_SETTINGS)); + sb.append(", ").append(projection.toJson(JSON_WRITER_SETTINGS, codec)); } sb.append(")"); if (!sort.isEmpty()) { - sb.append(".sort(" + sort.toJson(JSON_WRITER_SETTINGS) + ")"); + sb.append(".sort(").append(sort.toJson(JSON_WRITER_SETTINGS, codec)).append(")"); } if (queryMixin.getMetadata().getModifiers().getOffset() != null) { - sb.append(".skip(" + queryMixin.getMetadata().getModifiers().getOffset() + ")"); + sb.append(".skip(").append(queryMixin.getMetadata().getModifiers().getOffset()).append(")"); } if (queryMixin.getMetadata().getModifiers().getLimit() != null) { - sb.append(".limit(" + queryMixin.getMetadata().getModifiers().getLimit() + ")"); + sb.append(".limit(").append(queryMixin.getMetadata().getModifiers().getLimit()).append(")"); } return sb.toString(); } /** * Obtain the {@literal Mongo Shell} json query representation. - * + * * @return never {@literal null}. * @since 2.2 */ diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java index daa847c259..6d908df879 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/QuerydslRepositorySupportTests.java @@ -25,6 +25,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; + import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.annotation.Id; @@ -262,17 +263,23 @@ public void toJsonShouldRenderQuery() { public void toStringShouldRenderQuery() { QPerson p = QPerson.person; - SpringDataMongodbQuery query = repoSupport.from(p).where(p.lastname.eq("Matthews")); + User user = new User(); + user.setId("id"); + SpringDataMongodbQuery query = repoSupport.from(p) + .where(p.lastname.eq("Matthews").and(p.coworker.eq(user))); - assertThat(StringUtils.trimAllWhitespace(query.toString())).isEqualTo("find({\"lastname\":\"Matthews\"})"); + assertThat(StringUtils.trimAllWhitespace(query.toString())) + .isEqualTo("find({\"lastname\":\"Matthews\",\"coworker\":{\"$ref\":\"user\",\"$id\":\"id\"}})"); query = query.orderBy(p.firstname.asc()); assertThat(StringUtils.trimAllWhitespace(query.toString())) - .isEqualTo("find({\"lastname\":\"Matthews\"}).sort({\"firstname\":1})"); + .isEqualTo( + "find({\"lastname\":\"Matthews\",\"coworker\":{\"$ref\":\"user\",\"$id\":\"id\"}}).sort({\"firstname\":1})"); query = query.offset(1).limit(5); assertThat(StringUtils.trimAllWhitespace(query.toString())) - .isEqualTo("find({\"lastname\":\"Matthews\"}).sort({\"firstname\":1}).skip(1).limit(5)"); + .isEqualTo( + "find({\"lastname\":\"Matthews\",\"coworker\":{\"$ref\":\"user\",\"$id\":\"id\"}}).sort({\"firstname\":1}).skip(1).limit(5)"); } @Data