From 28b744c3c4eaa0a8c87ba5e3d3628c9c3ddcc0ae Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 21 Jan 2021 10:31:54 +0100 Subject: [PATCH 1/3] 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 f783756e33..dd1999471b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.4-SNAPSHOT + 3.1.x-GH-3055-SNAPSHOT pom Spring Data MongoDB diff --git a/spring-data-mongodb-benchmarks/pom.xml b/spring-data-mongodb-benchmarks/pom.xml index f8c3dd56dd..03a5ab932b 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 - 3.1.4-SNAPSHOT + 3.1.x-GH-3055-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 20f6c08ce1..75db30736e 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 - 3.1.4-SNAPSHOT + 3.1.x-GH-3055-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index f6f7f1e384..b2790a9cc8 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 3.1.4-SNAPSHOT + 3.1.x-GH-3055-SNAPSHOT ../pom.xml From 21e8f3863ca703707053652ec6bebd4bb4daf295 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 21 Jan 2021 11:11:02 +0100 Subject: [PATCH 2/3] Update count vs. estimatedCount documentation. Closes #3055 --- .../mongodb/core/ExecutableFindOperation.java | 5 ++++ .../data/mongodb/core/MongoOperations.java | 24 +++++++++++++++++++ .../mongodb/core/ReactiveFindOperation.java | 6 +++++ .../mongodb/core/ReactiveMongoOperations.java | 24 +++++++++++++++++++ src/main/asciidoc/reference/mongodb.adoc | 1 + 5 files changed, 60 insertions(+) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java index 28dd7dddcc..d67212bdc6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ExecutableFindOperation.java @@ -125,6 +125,11 @@ default Optional first() { /** * Get the number of matching elements. + *

+ * This method uses an {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) aggregation + * execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees shard, + * session and transaction compliance. In case an inaccurate count satisfies the applications needs use + * {@link MongoOperations#estimatedCount(String)} for empty queries instead. * * @return total number of matching elements. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java index 5a5a3b7fc5..ffa301a280 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOperations.java @@ -1160,6 +1160,12 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. + *

+ * This method uses an + * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) + * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees + * shard, session and transaction compliance. In case an inaccurate count satisfies the applications needs use + * {@link #estimatedCount(Class)} for empty queries instead. * * @param query the {@link Query} class that specifies the criteria used to find documents. Must not be * {@literal null}. @@ -1176,6 +1182,12 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. + *

+ * This method uses an + * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) + * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees + * shard, session and transaction compliance. In case an inaccurate count satisfies the applications needs use + * {@link #estimatedCount(String)} for empty queries instead. * * @param query the {@link Query} class that specifies the criteria used to find documents. * @param collectionName must not be {@literal null} or empty. @@ -1187,6 +1199,9 @@ T findAndReplace(Query query, S replacement, FindAndReplaceOptions option /** * Estimate the number of documents, in the collection {@link #getCollectionName(Class) identified by the given type}, * based on collection statistics. + *

+ * Please make sure to read the MongoDB reference documentation about limitations on eg. sharded cluster or inside + * transactions. * * @param entityClass must not be {@literal null}. * @return the estimated number of documents. @@ -1200,6 +1215,9 @@ default long estimatedCount(Class entityClass) { /** * Estimate the number of documents in the given collection based on collection statistics. + *

+ * Please make sure to read the MongoDB reference documentation about limitations on eg. sharded cluster or inside + * transactions. * * @param collectionName must not be {@literal null}. * @return the estimated number of documents. @@ -1214,6 +1232,12 @@ default long estimatedCount(Class entityClass) { * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. + *

+ * This method uses an + * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) + * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees + * shard, session and transaction compliance. In case an inaccurate count satisfies the applications needs use + * {@link #estimatedCount(String)} for empty queries instead. * * @param query the {@link Query} class that specifies the criteria used to find documents. Must not be * {@literal null}. diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java index b66f6e176d..9a65090922 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveFindOperation.java @@ -106,6 +106,12 @@ interface TerminatingFind { /** * Get the number of matching elements. + *

+ * This method uses an + * {@link com.mongodb.reactivestreams.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) + * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but + * guarantees shard, session and transaction compliance. In case an inaccurate count satisfies the applications + * needs use {@link ReactiveMongoOperations#estimatedCount(String)} for empty queries instead. * * @return {@link Mono} emitting total number of matching elements. Never {@literal null}. */ diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java index 2d981fd1b4..a1a0925b70 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoOperations.java @@ -940,6 +940,12 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. + *

+ * This method uses an + * {@link com.mongodb.reactivestreams.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) + * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees + * shard, session and transaction compliance. In case an inaccurate count satisfies the applications needs use + * {@link #estimatedCount(Class)} for empty queries instead. * * @param query the {@link Query} class that specifies the criteria used to find documents. Must not be * {@literal null}. @@ -956,6 +962,12 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. + *

+ * This method uses an + * {@link com.mongodb.reactivestreams.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) + * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees + * shard, session and transaction compliance. In case an inaccurate count satisfies the applications needs use + * {@link #estimatedCount(String)} for empty queries instead. * * @param query the {@link Query} class that specifies the criteria used to find documents. * @param collectionName must not be {@literal null} or empty. @@ -971,6 +983,12 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions * influence on the resulting number of documents found as those values are passed on to the server and potentially * limit the range and order within which the server performs the count operation. Use an {@literal unpaged} query to * count all matches. + *

+ * This method uses an + * {@link com.mongodb.reactivestreams.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions) + * aggregation execution} even for empty {@link Query queries} which may have an impact on performance, but guarantees + * shard, session and transaction compliance. In case an inaccurate count satisfies the applications needs use + * {@link #estimatedCount(String)} for empty queries instead. * * @param query the {@link Query} class that specifies the criteria used to find documents. Must not be * {@literal null}. @@ -983,6 +1001,9 @@ Mono findAndReplace(Query query, S replacement, FindAndReplaceOptions /** * Estimate the number of documents, in the collection {@link #getCollectionName(Class) identified by the given type}, * based on collection statistics. + *

+ * Please make sure to read the MongoDB reference documentation about limitations on eg. sharded cluster or inside + * transactions. * * @param entityClass must not be {@literal null}. * @return a {@link Mono} emitting the estimated number of documents. @@ -996,6 +1017,9 @@ default Mono estimatedCount(Class entityClass) { /** * Estimate the number of documents in the given collection based on collection statistics. + *

+ * Please make sure to read the MongoDB reference documentation about limitations on eg. sharded cluster or inside + * transactions. * * @param collectionName must not be {@literal null}. * @return a {@link Mono} emitting the estimated number of documents. diff --git a/src/main/asciidoc/reference/mongodb.adoc b/src/main/asciidoc/reference/mongodb.adoc index 99e2e0ec70..0986b0a836 100644 --- a/src/main/asciidoc/reference/mongodb.adoc +++ b/src/main/asciidoc/reference/mongodb.adoc @@ -2221,6 +2221,7 @@ With the introduction of <> this was no longer possible beca So in version 2.x `MongoOperations.count()` would use the collection statistics if no transaction was in progress, and the aggregation variant if so. As of Spring Data MongoDB 3.x any `count` operation uses regardless the existence of filter criteria the aggregation-based count approach via MongoDBs `countDocuments`. +If the application is fine with the limitations of working upon collection statistics `MongoOperations.estimatedCount()` offers an alternative. [NOTE] ==== From 7437f5ed79e40167b05035d4d8cd08eb95485171 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 21 Jan 2021 11:22:44 +0100 Subject: [PATCH 3/3] Allow access to mongoDatabaseFactory used in ReactiveMongoTemplate. By offering a getter method for the ReactiveMongoDatabaseFactory users subclassing ReactiveMongoTemplate could evaluate the current transaction state via ReactiveMongoDatabaseUtils.isTransactionActive(getDatabaseFactory()). This change also aligns the reactive and imperative template implementation in that regard. Closes #3540 --- .../data/mongodb/core/MongoTemplate.java | 14 +++++++++++++- .../data/mongodb/core/ReactiveMongoTemplate.java | 8 ++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index fdc42119fa..89ff6b3d6c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -28,7 +28,6 @@ import org.bson.conversions.Bson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -3454,7 +3453,20 @@ public void close() { } } + /** + * @deprecated since 3.1.4. Use {@link #getMongoDatabaseFactory()} instead. + * @return the {@link MongoDatabaseFactory} in use. + */ + @Deprecated public MongoDatabaseFactory getMongoDbFactory() { + return getMongoDatabaseFactory(); + } + + /** + * @return the {@link MongoDatabaseFactory} in use. + * @since 3.1.4 + */ + public MongoDatabaseFactory getMongoDatabaseFactory() { return mongoDbFactory; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java index b81a87fa84..48a11ffa09 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/ReactiveMongoTemplate.java @@ -2730,6 +2730,14 @@ protected WriteConcern prepareWriteConcern(MongoAction mongoAction) { return potentiallyForceAcknowledgedWrite(wc); } + /** + * @return the {@link MongoDatabaseFactory} in use. + * @since 3.1.4 + */ + public ReactiveMongoDatabaseFactory getMongoDatabaseFactory() { + return mongoDatabaseFactory; + } + @Nullable private WriteConcern potentiallyForceAcknowledgedWrite(@Nullable WriteConcern wc) {