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 0e5feea19..f889e95c7 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
@@ -57,8 +57,7 @@ import com.mongodb.client.result.UpdateResult;
/**
* Interface that specifies a basic set of MongoDB operations. Implemented by {@link MongoTemplate}. Not often used but
* a useful option for extensibility and testability (as it can be easily mocked, stubbed, or be the target of a JDK
- * proxy).
- *
+ * proxy).
* NOTE: Some operations cannot be executed within a MongoDB transaction. Please refer to the MongoDB
* specific documentation to learn more about Multi
* Document Transactions.
@@ -84,7 +83,7 @@ public interface MongoOperations extends FluentMongoOperations {
String getCollectionName(Class> entityClass);
/**
- * Execute the a MongoDB command expressed as a JSON string. Parsing is delegated to {@link Document#parse(String)} to
+ * Execute a MongoDB command expressed as a JSON string. Parsing is delegated to {@link Document#parse(String)} to
* obtain the {@link Document} holding the actual command. Any errors that result from executing this command will be
* converted into Spring's DAO exception hierarchy.
*
@@ -124,8 +123,7 @@ public interface MongoOperations extends FluentMongoOperations {
void executeQuery(Query query, String collectionName, DocumentCallbackHandler dch);
/**
- * Executes a {@link DbCallback} translating any exceptions as necessary.
- *
+ * Executes a {@link DbCallback} translating any exceptions as necessary.
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param action callback object that specifies the MongoDB actions to perform on the passed in DB instance. Must not
@@ -137,8 +135,7 @@ public interface MongoOperations extends FluentMongoOperations {
T execute(DbCallback action);
/**
- * Executes the given {@link CollectionCallback} on the entity collection of the specified class.
- *
+ * Executes the given {@link CollectionCallback} on the entity collection of the specified class.
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param entityClass class that determines the collection to use. Must not be {@literal null}.
@@ -150,8 +147,7 @@ public interface MongoOperations extends FluentMongoOperations {
T execute(Class> entityClass, CollectionCallback action);
/**
- * Executes the given {@link CollectionCallback} on the collection of the given name.
- *
+ * Executes the given {@link CollectionCallback} on the collection of the given name.
* Allows for returning a result object, that is a domain object or a collection of domain objects.
*
* @param collectionName the name of the collection that specifies which {@link MongoCollection} instance will be
@@ -175,8 +171,7 @@ public interface MongoOperations extends FluentMongoOperations {
/**
* Obtain a {@link ClientSession session} bound instance of {@link SessionScoped} binding the {@link ClientSession}
- * provided by the given {@link Supplier} to each and every command issued against MongoDB.
- *
+ * provided by the given {@link Supplier} to each and every command issued against MongoDB.
* Note: It is up to the caller to manage the {@link ClientSession} lifecycle. Use the
* {@link SessionScoped#execute(SessionCallback, Consumer)} hook to potentially close the {@link ClientSession}.
*
@@ -211,8 +206,7 @@ public interface MongoOperations extends FluentMongoOperations {
}
/**
- * Obtain a {@link ClientSession} bound instance of {@link MongoOperations}.
- *
+ * Obtain a {@link ClientSession} bound instance of {@link MongoOperations}.
* Note: It is up to the caller to manage the {@link ClientSession} lifecycle.
*
* @param session must not be {@literal null}.
@@ -299,8 +293,7 @@ public interface MongoOperations extends FluentMongoOperations {
* Get a {@link MongoCollection} by its name. The returned collection may not exists yet (except in local memory) and
* is created on first interaction with the server. Collections can be explicitly created via
* {@link #createCollection(Class)}. Please make sure to check if the collection {@link #collectionExists(Class)
- * exists} first.
- *
+ * exists} first.
* Translate any exceptions as necessary.
*
* @param collectionName name of the collection. Must not be {@literal null}.
@@ -309,8 +302,7 @@ public interface MongoOperations extends FluentMongoOperations {
MongoCollection getCollection(String collectionName);
/**
- * Check to see if a collection with a name indicated by the entity class exists.
- *
+ * Check to see if a collection with a name indicated by the entity class exists.
* Translate any exceptions as necessary.
*
* @param entityClass class that determines the name of the collection. Must not be {@literal null}.
@@ -319,8 +311,7 @@ public interface MongoOperations extends FluentMongoOperations {
boolean collectionExists(Class entityClass);
/**
- * Check to see if a collection with a given name exists.
- *
+ * Check to see if a collection with a given name exists.
* Translate any exceptions as necessary.
*
* @param collectionName name of the collection. Must not be {@literal null}.
@@ -329,8 +320,7 @@ public interface MongoOperations extends FluentMongoOperations {
boolean collectionExists(String collectionName);
/**
- * Drop the collection with the name indicated by the entity class.
- *
+ * Drop the collection with the name indicated by the entity class.
* Translate any exceptions as necessary.
*
* @param entityClass class that determines the collection to drop/delete. Must not be {@literal null}.
@@ -338,8 +328,7 @@ public interface MongoOperations extends FluentMongoOperations {
void dropCollection(Class entityClass);
/**
- * Drop the collection with the given name.
- *
+ * Drop the collection with the given name.
* Translate any exceptions as necessary.
*
* @param collectionName name of the collection to drop/delete.
@@ -402,11 +391,9 @@ public interface MongoOperations extends FluentMongoOperations {
BulkOperations bulkOps(BulkMode mode, @Nullable Class> entityType, String collectionName);
/**
- * Query for a list of objects of type T from the collection used by the entity class.
- *
+ * Query for a list of objects of type T from the collection used by the entity class.
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
- * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
- *
+ * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
* to map objects since the test for class type is done in the client and not on the server.
*
@@ -416,11 +403,9 @@ public interface MongoOperations extends FluentMongoOperations {
List findAll(Class entityClass);
/**
- * Query for a list of objects of type T from the specified collection.
- *
+ * Query for a list of objects of type T from the specified collection.
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
- * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
- *
+ * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* If your collection does not contain a homogeneous collection of types, this operation will not be an efficient way
* to map objects since the test for class type is done in the client and not on the server.
*
@@ -538,12 +523,10 @@ public interface MongoOperations extends FluentMongoOperations {
CloseableIterator aggregateStream(TypedAggregation> aggregation, String collectionName, Class outputType);
/**
- * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}.
- *
+ * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}.
* Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that
* needs to be closed. The raw results will be mapped to the given entity class and are returned as stream. The name
- * of the inputCollection is derived from the inputType of the aggregation.
- *
+ * of the inputCollection is derived from the inputType of the aggregation.
* Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling
* explanation mode will throw an {@link IllegalArgumentException}.
*
@@ -556,11 +539,9 @@ public interface MongoOperations extends FluentMongoOperations {
CloseableIterator aggregateStream(TypedAggregation> aggregation, Class outputType);
/**
- * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}.
- *
+ * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}.
* Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that
- * needs to be closed. The raw results will be mapped to the given entity class.
- *
+ * needs to be closed. The raw results will be mapped to the given entity class.
* Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling
* explanation mode will throw an {@link IllegalArgumentException}.
*
@@ -575,11 +556,9 @@ public interface MongoOperations extends FluentMongoOperations {
CloseableIterator aggregateStream(Aggregation aggregation, Class> inputType, Class outputType);
/**
- * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}.
- *
+ * Execute an aggregation operation backed by a Mongo DB {@link com.mongodb.client.AggregateIterable}.
* Returns a {@link CloseableIterator} that wraps the a Mongo DB {@link com.mongodb.client.AggregateIterable} that
- * needs to be closed. The raw results will be mapped to the given entity class.
- *
+ * needs to be closed. The raw results will be mapped to the given entity class.
* Aggregation streaming can't be used with {@link AggregationOptions#isExplain() aggregation explain}. Enabling
* explanation mode will throw an {@link IllegalArgumentException}.
*
@@ -709,11 +688,9 @@ public interface MongoOperations extends FluentMongoOperations {
/**
* Map the results of an ad-hoc query on the collection for the entity class to a single instance of an object of the
- * specified type.
- *
+ * specified type.
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
- * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
- *
+ * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
@@ -727,11 +704,9 @@ public interface MongoOperations extends FluentMongoOperations {
/**
* Map the results of an ad-hoc query on the specified collection to a single instance of an object of the specified
- * type.
- *
+ * type.
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
- * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
- *
+ * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
@@ -775,11 +750,9 @@ public interface MongoOperations extends FluentMongoOperations {
boolean exists(Query query, @Nullable Class> entityClass, String collectionName);
/**
- * Map the results of an ad-hoc query on the collection for the entity class to a List of the specified type.
- *
+ * Map the results of an ad-hoc query on the collection for the entity class to a List of the specified type.
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
- * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
- *
+ * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
@@ -791,11 +764,9 @@ public interface MongoOperations extends FluentMongoOperations {
List find(Query query, Class entityClass);
/**
- * Map the results of an ad-hoc query on the specified collection to a List of the specified type.
- *
+ * Map the results of an ad-hoc query on the specified collection to a List of the specified type.
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
- * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
- *
+ * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
@@ -1127,10 +1098,8 @@ public interface MongoOperations extends FluentMongoOperations {
/**
* Map the results of an ad-hoc query on the collection for the entity type to a single instance of an object of the
* specified type. The first document that matches the query is returned and also removed from the collection in the
- * database.
- *
- * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}.
- *
+ * database.
+ * The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}.
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
@@ -1147,8 +1116,7 @@ public interface MongoOperations extends FluentMongoOperations {
* type. The first document that matches the query is returned and also removed from the collection in the database.
*
* The object is converted from the MongoDB native representation using an instance of {@see MongoConverter}. Unless
- * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
- *
+ * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* The query is specified as a {@link Query} which can be created either using the {@link BasicQuery} or the more
* feature rich {@link Query}.
*
@@ -1167,8 +1135,96 @@ public interface MongoOperations extends FluentMongoOperations {
* NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
* 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.
+ * count all matches.
+ * This method may choose to use {@link #estimatedCount(Class)} for empty queries instead of running an
+ * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions)
+ * aggregation execution} which may have an impact on performance.
+ *
+ * @param query the {@link Query} class that specifies the criteria used to find documents. Must not be
+ * {@literal null}.
+ * @param entityClass class that determines the collection to use. Must not be {@literal null}.
+ * @return the count of matching documents.
+ * @see #exactCount(Query, Class)
+ * @see #estimatedCount(Class)
+ */
+ long count(Query query, Class> entityClass);
+
+ /**
+ * Returns the number of documents for the given {@link Query} querying the given collection. The given {@link Query}
+ * must solely consist of document field references as we lack type information to map potential property references
+ * onto document fields. Use {@link #count(Query, Class, String)} to get full type specific support.
+ * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
+ * 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 may choose to use {@link #estimatedCount(Class)} for empty queries instead of running an
+ * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions)
+ * aggregation execution} which may have an impact on performance.
+ *
+ * @param query the {@link Query} class that specifies the criteria used to find documents.
+ * @param collectionName must not be {@literal null} or empty.
+ * @return the count of matching documents.
+ * @see #count(Query, Class, String)
+ * @see #exactCount(Query, String)
+ * @see #estimatedCount(String)
+ */
+ long count(Query query, String collectionName);
+
+ /**
+ * Returns the number of documents for the given {@link Query} by querying the given collection using the given entity
+ * class to map the given {@link Query}.
+ * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
+ * 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 may choose to use {@link #estimatedCount(Class)} for empty queries instead of running an
+ * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions)
+ * aggregation execution} which may have an impact on performance.
+ *
+ * @param query the {@link Query} class that specifies the criteria used to find documents. Must not be
+ * {@literal null}.
+ * @param entityClass the parametrized type. Can be {@literal null}.
+ * @param collectionName must not be {@literal null} or empty.
+ * @return the count of matching documents.
+ * @see #count(Query, Class, String)
+ * @see #estimatedCount(String)
+ */
+ long count(Query query, @Nullable Class> entityClass, String collectionName);
+
+ /**
+ * 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.
+ * @since 3.1
+ */
+ default long estimatedCount(Class> entityClass) {
+
+ Assert.notNull(entityClass, "Entity class must not be null!");
+ return estimatedCount(getCollectionName(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.
+ * @since 3.1
+ */
+ long estimatedCount(String collectionName);
+
+ /**
+ * Returns the number of documents for the given {@link Query} by querying the collection of the given entity class.
*
+ * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
+ * 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
@@ -1192,8 +1248,7 @@ public interface MongoOperations extends FluentMongoOperations {
* NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
* 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.
- *
+ * 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
@@ -1216,8 +1271,7 @@ public interface MongoOperations extends FluentMongoOperations {
* NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
* 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.
- *
+ * 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
@@ -1234,104 +1288,13 @@ public interface MongoOperations extends FluentMongoOperations {
long exactCount(Query query, @Nullable Class> entityClass, String collectionName);
/**
- * Returns the number of documents for the given {@link Query} by querying the collection of the given entity class.
- *
- * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
- * 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 may choose to use {@link #estimatedCount(Class)} for empty queries instead of running an
- * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions)
- * aggregation execution} which may have an impact on performance.
- *
- * @param query the {@link Query} class that specifies the criteria used to find documents. Must not be
- * {@literal null}.
- * @param entityClass class that determines the collection to use. Must not be {@literal null}.
- * @return the count of matching documents.
- */
- long count(Query query, Class> entityClass);
-
- /**
- * Returns the number of documents for the given {@link Query} querying the given collection. The given {@link Query}
- * must solely consist of document field references as we lack type information to map potential property references
- * onto document fields. Use {@link #count(Query, Class, String)} to get full type specific support.
- * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
- * 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 may choose to use {@link #estimatedCount(Class)} for empty queries instead of running an
- * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions)
- * aggregation execution} which may have an impact on performance.
- *
- * @param query the {@link Query} class that specifies the criteria used to find documents.
- * @param collectionName must not be {@literal null} or empty.
- * @return the count of matching documents.
- * @see #count(Query, Class, String)
- */
- long count(Query query, String collectionName);
-
- /**
- * 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.
- * @since 3.1
- */
- default long estimatedCount(Class> entityClass) {
-
- Assert.notNull(entityClass, "Entity class must not be null!");
- return estimatedCount(getCollectionName(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.
- * @since 3.1
- */
- long estimatedCount(String collectionName);
-
- /**
- * Returns the number of documents for the given {@link Query} by querying the given collection using the given entity
- * class to map the given {@link Query}.
- * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
- * 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 may choose to use {@link #estimatedCount(Class)} for empty queries instead of running an
- * {@link com.mongodb.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions)
- * aggregation execution} which may have an impact on performance.
- *
- * @param query the {@link Query} class that specifies the criteria used to find documents. Must not be
- * {@literal null}.
- * @param entityClass the parametrized type. Can be {@literal null}.
- * @param collectionName must not be {@literal null} or empty.
- * @return the count of matching documents.
- */
- long count(Query query, @Nullable Class> entityClass, String collectionName);
-
- /**
- * Insert the object into the collection for the entity type of the object to save.
- *
- * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}.
- *
+ * Insert the object into the collection for the entity type of the object to save.
+ * The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}.
* If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
* Spring's
- * Type Conversion" for more details.
- *
+ * Type Conversion" for more details.
* Insert is used to initially store the object into the database. To update an existing object use the save method.
*
* The {@code objectToSave} must not be collection-like.
@@ -1343,11 +1306,9 @@ public interface MongoOperations extends FluentMongoOperations {
T insert(T objectToSave);
/**
- * Insert the object into the specified collection.
- *
+ * Insert the object into the specified collection.
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
- * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
- *
+ * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* Insert is used to initially store the object into the database. To update an existing object use the save method.
*
* The {@code objectToSave} must not be collection-like.
@@ -1388,17 +1349,14 @@ public interface MongoOperations extends FluentMongoOperations {
/**
* Save the object to the collection for the entity type of the object to save. This will perform an insert if the
- * object is not already present, that is an 'upsert'.
- *
+ * object is not already present, that is an 'upsert'.
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
- * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
- *
+ * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
* property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
* Spring's
- * Type Conversion" for more details.
- *
+ * Type Conversion" for more details.
* The {@code objectToSave} must not be collection-like.
*
* @param objectToSave the object to store in the collection. Must not be {@literal null}.
@@ -1409,16 +1367,14 @@ public interface MongoOperations extends FluentMongoOperations {
/**
* Save the object to the specified collection. This will perform an insert if the object is not already present, that
- * is an 'upsert'.
- *
+ * is an 'upsert'.
* The object is converted to the MongoDB native representation using an instance of {@see MongoConverter}. Unless
- * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
- *
+ * configured otherwise, an instance of {@link MappingMongoConverter} will be used.
* If your object has an "Id' property, it will be set with the generated Id from MongoDB. If your Id property is a
* String then MongoDB ObjectId will be used to populate that string. Otherwise, the conversion from ObjectId to your
- * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API.
- * See Spring's Type Conversion for more details.
- *
+ * property type will be handled by Spring's BeanWrapper class that leverages Type Conversion API. See
+ * Spring's Type
+ * Conversion for more details.
* The {@code objectToSave} must not be collection-like.
*
* @param objectToSave the object to store in the collection. Must not be {@literal null}.
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 b8bac461d..b95f9b38b 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
@@ -348,10 +348,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
/**
- * En-/Disable usage of estimated count.
+ * Configure whether to use estimated count. Defaults to exact counting.
*
- * @param enabled if {@literal true} {@link MongoCollection#estimatedDocumentCount()} ()} will we used for unpaged,
- * empty {@link Query queries}.
+ * @param enabled use {@link com.mongodb.client.MongoCollection#estimatedDocumentCount()} for unpaged and empty
+ * {@link Query queries} if {@code true}.
* @since 3.4
*/
public void useEstimatedCount(boolean enabled) {
@@ -359,10 +359,10 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
}
/**
- * En-/Disable usage of estimated count based on the given {@link BiPredicate estimationFilter}.
+ * Configure whether to use estimated count based on the given {@link BiPredicate estimationFilter}.
*
- * @param enabled if {@literal true} {@link MongoCollection#estimatedDocumentCount()} will we used for {@link Document
- * filter queries} that pass the given {@link BiPredicate estimationFilter}.
+ * @param enabled use {@link com.mongodb.client.MongoCollection#estimatedDocumentCount()} for unpaged and empty
+ * {@link Query queries} if {@code true}.
* @param estimationFilter the {@link BiPredicate filter}.
* @since 3.4
*/
@@ -453,8 +453,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
MongoPersistentEntity> persistentEntity = mappingContext.getPersistentEntity(entityType);
QueryContext queryContext = queryOperations.createQueryContext(query);
- EntityProjection projection = operations.introspectProjection(returnType,
- entityType);
+ EntityProjection projection = operations.introspectProjection(returnType, entityType);
Document mappedQuery = queryContext.getMappedQuery(persistentEntity);
Document mappedFields = queryContext.getMappedFields(persistentEntity, projection);
@@ -1003,8 +1002,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
.withOptions(AggregationOptions.builder().collation(near.getCollation()).build());
AggregationResults results = aggregate($geoNear, collection, Document.class);
- EntityProjection projection = operations.introspectProjection(returnType,
- domainType);
+ EntityProjection projection = operations.introspectProjection(returnType, domainType);
DocumentCallback> callback = new GeoNearResultDocumentCallback<>(distanceField,
new ProjectingReadCallback<>(mongoConverter, projection, collection), near.getMetric());
@@ -1091,8 +1089,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
MongoPersistentEntity> entity = mappingContext.getPersistentEntity(entityType);
QueryContext queryContext = queryOperations.createQueryContext(query);
- EntityProjection projection = operations.introspectProjection(resultType,
- entityType);
+ EntityProjection projection = operations.introspectProjection(resultType, entityType);
Document mappedQuery = queryContext.getMappedQuery(entity);
Document mappedFields = queryContext.getMappedFields(entity, projection);
Document mappedSort = queryContext.getMappedSort(entity);
@@ -1104,8 +1101,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
maybeCallBeforeSave(replacement, mappedReplacement, collectionName);
T saved = doFindAndReplace(collectionName, mappedQuery, mappedFields, mappedSort,
- queryContext.getCollation(entityType).orElse(null), entityType, mappedReplacement, options,
- projection);
+ queryContext.getCollation(entityType).orElse(null), entityType, mappedReplacement, options, projection);
if (saved != null) {
maybeEmitEvent(new AfterSaveEvent<>(saved, mappedReplacement, collectionName));
@@ -1149,17 +1145,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return count(query, null, collectionName);
}
- @Override
- public long exactCount(Query query, @Nullable Class> entityClass, String collectionName) {
-
- CountContext countContext = queryOperations.countQueryContext(query);
-
- CountOptions options = countContext.getCountOptions(entityClass);
- Document mappedQuery = countContext.getMappedQuery(entityClass, mappingContext::getPersistentEntity);
-
- return doExactCount(collectionName, mappedQuery, options);
- }
-
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.MongoOperations#count(org.springframework.data.mongodb.core.query.Query, java.lang.Class, java.lang.String)
@@ -1177,7 +1162,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return doCount(collectionName, mappedQuery, options);
}
- @SuppressWarnings("ConstantConditions")
protected long doCount(String collectionName, Document filter, CountOptions options) {
if (LOGGER.isDebugEnabled()) {
@@ -1188,6 +1172,30 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return countExecution.countDocuments(collectionName, filter, options);
}
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.mongodb.core.MongoOperations#estimatedCount(java.lang.String)
+ */
+ @Override
+ public long estimatedCount(String collectionName) {
+ return doEstimatedCount(collectionName, new EstimatedDocumentCountOptions());
+ }
+
+ protected long doEstimatedCount(String collectionName, EstimatedDocumentCountOptions options) {
+ return execute(collectionName, collection -> collection.estimatedDocumentCount(options));
+ }
+
+ @Override
+ public long exactCount(Query query, @Nullable Class> entityClass, String collectionName) {
+
+ CountContext countContext = queryOperations.countQueryContext(query);
+
+ CountOptions options = countContext.getCountOptions(entityClass);
+ Document mappedQuery = countContext.getMappedQuery(entityClass, mappingContext::getPersistentEntity);
+
+ return doExactCount(collectionName, mappedQuery, options);
+ }
+
protected long doExactCount(String collectionName, Document filter, CountOptions options) {
return execute(collectionName,
collection -> collection.countDocuments(CountQuery.of(filter).toQueryDocument(), options));
@@ -1208,19 +1216,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
return options.getLimit() <= 0 && options.getSkip() <= 0;
}
- /*
- * (non-Javadoc)
- * @see org.springframework.data.mongodb.core.MongoOperations#estimatedCount(java.lang.String)
- */
- @Override
- public long estimatedCount(String collectionName) {
- return doEstimatedCount(collectionName, new EstimatedDocumentCountOptions());
- }
-
- protected long doEstimatedCount(String collectionName, EstimatedDocumentCountOptions options) {
- return execute(collectionName, collection -> collection.estimatedDocumentCount(options));
- }
-
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.MongoOperations#insert(java.lang.Object)
@@ -2575,8 +2570,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
MongoPersistentEntity> entity = mappingContext.getPersistentEntity(entityClass);
QueryContext queryContext = queryOperations.createQueryContext(new BasicQuery(query, fields));
- Document mappedFields = queryContext.getMappedFields(entity,
- EntityProjection.nonProjecting(entityClass));
+ Document mappedFields = queryContext.getMappedFields(entity, EntityProjection.nonProjecting(entityClass));
Document mappedQuery = queryContext.getMappedQuery(entity);
if (LOGGER.isDebugEnabled()) {
@@ -2628,8 +2622,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
MongoPersistentEntity> entity = mappingContext.getPersistentEntity(entityClass);
QueryContext queryContext = queryOperations.createQueryContext(new BasicQuery(query, fields));
- Document mappedFields = queryContext.getMappedFields(entity,
- EntityProjection.nonProjecting(entityClass));
+ Document mappedFields = queryContext.getMappedFields(entity, EntityProjection.nonProjecting(entityClass));
Document mappedQuery = queryContext.getMappedQuery(entity);
if (LOGGER.isDebugEnabled()) {
@@ -2651,8 +2644,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Class targetClass, CursorPreparer preparer) {
MongoPersistentEntity> entity = mappingContext.getPersistentEntity(sourceClass);
- EntityProjection projection = operations.introspectProjection(targetClass,
- sourceClass);
+ EntityProjection projection = operations.introspectProjection(targetClass, sourceClass);
QueryContext queryContext = queryOperations.createQueryContext(new BasicQuery(query, fields));
Document mappedFields = queryContext.getMappedFields(entity, projection);
@@ -2667,7 +2659,6 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
new ProjectingReadCallback<>(mongoConverter, projection, collectionName), collectionName);
}
-
/**
* Convert given {@link CollectionOptions} to a document and take the domain type information into account when
* creating a mapped schema for validation.
@@ -2747,8 +2738,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
/**
* Map the results of an ad-hoc query on the default MongoDB collection to an object using the template's converter.
- * The first document that matches the query is returned and also removed from the collection in the database.
- *
+ * The first document that matches the query is returned and also removed from the collection in the database.
* The query document is specified as a standard Document and so is the fields specification.
*
* @param collectionName name of the collection to retrieve the objects from
@@ -2826,8 +2816,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Document mappedSort, @Nullable com.mongodb.client.model.Collation collation, Class> entityType,
Document replacement, FindAndReplaceOptions options, Class resultType) {
- EntityProjection projection = operations.introspectProjection(resultType,
- entityType);
+ EntityProjection projection = operations.introspectProjection(resultType, entityType);
return doFindAndReplace(collectionName, mappedQuery, mappedFields, mappedSort, collation, entityType, replacement,
options, projection);
@@ -2855,10 +2844,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
Document replacement, FindAndReplaceOptions options, EntityProjection projection) {
if (LOGGER.isDebugEnabled()) {
- LOGGER.debug(String.format(
- "findAndReplace using query: %s fields: %s sort: %s for class: %s and replacement: %s " + "in collection: %s",
- serializeToJsonSafely(mappedQuery), serializeToJsonSafely(mappedFields), serializeToJsonSafely(mappedSort),
- entityType, serializeToJsonSafely(replacement), collectionName));
+ LOGGER
+ .debug(String.format(
+ "findAndReplace using query: %s fields: %s sort: %s for class: %s and replacement: %s "
+ + "in collection: %s",
+ serializeToJsonSafely(mappedQuery), serializeToJsonSafely(mappedFields),
+ serializeToJsonSafely(mappedSort), entityType, serializeToJsonSafely(replacement), collectionName));
}
return executeFindOneInternal(
@@ -3051,8 +3042,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("findOne using query: %s fields: %s in db.collection: %s",
- serializeToJsonSafely(query),
- serializeToJsonSafely(fields.orElseGet(Document::new)),
+ serializeToJsonSafely(query), serializeToJsonSafely(fields.orElseGet(Document::new)),
collection.getNamespace() != null ? collection.getNamespace().getFullName() : "n/a"));
}
@@ -3318,8 +3308,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
private final EntityProjection projection;
private final String collectionName;
- ProjectingReadCallback(MongoConverter mongoConverter, EntityProjection projection,
- String collectionName) {
+ ProjectingReadCallback(MongoConverter mongoConverter, EntityProjection projection, String collectionName) {
this.mongoConverter = mongoConverter;
this.projection = projection;
@@ -3598,8 +3587,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
/**
* {@link MongoTemplate} extension bound to a specific {@link ClientSession} that is applied when interacting with the
- * server through the driver API.
- *
+ * server through the driver API.
* The prepare steps for {@link MongoDatabase} and {@link MongoCollection} proxy the target and invoke the desired
* target method matching the actual arguments plus a {@link ClientSession}.
*
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 d50355dac..1bde11633 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
@@ -91,7 +91,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
ReactiveIndexOperations indexOps(Class> entityClass);
/**
- * Execute the a MongoDB command expressed as a JSON string. This will call the method JSON.parse that is part of the
+ * Execute a MongoDB command expressed as a JSON string. This will call the method JSON.parse that is part of the
* MongoDB driver to convert the JSON string to a Document. Any errors that result from executing this command will be
* converted into Spring's DAO exception hierarchy.
*
@@ -939,80 +939,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
* NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
* 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}.
- * @param entityClass class that determines the collection to use. Must not be {@literal null}.
- * @return the count of matching documents.
- * @since 3.4
- */
- default Mono exactCount(Query query, Class> entityClass) {
- return exactCount(query, entityClass, getCollectionName(entityClass));
- }
-
- /**
- * Returns the number of documents for the given {@link Query} querying the given collection. The given {@link Query}
- * must solely consist of document field references as we lack type information to map potential property references
- * onto document fields. Use {@link #count(Query, Class, String)} to get full type specific support.
- * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
- * 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.
- * @return the count of matching documents.
- * @see #count(Query, Class, String)
- * @since 3.4
- */
- default Mono exactCount(Query query, String collectionName) {
- return exactCount(query, null, collectionName);
- }
-
- /**
- * Returns the number of documents for the given {@link Query} by querying the given collection using the given entity
- * class to map the given {@link Query}.
- * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
- * 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}.
- * @param entityClass the parametrized type. Can be {@literal null}.
- * @param collectionName must not be {@literal null} or empty.
- * @return the count of matching documents.
- * @since 3.4
- */
- Mono exactCount(Query query, @Nullable Class> entityClass, String collectionName);
-
- /**
- * Returns the number of documents for the given {@link Query} by querying the collection of the given entity class.
- *
- * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
- * 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.
- *
+ * count all matches.
* This method may choose to use {@link #estimatedCount(Class)} for empty queries instead of running an
* {@link com.mongodb.reactivestreams.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions)
* aggregation execution} which may have an impact on performance.
@@ -1021,6 +948,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
* {@literal null}.
* @param entityClass class that determines the collection to use. Must not be {@literal null}.
* @return the count of matching documents.
+ * @see #exactCount(Query, Class)
+ * @see #estimatedCount(Class)
*/
Mono count(Query query, Class> entityClass);
@@ -1031,8 +960,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
* NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
* 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.
- *
+ * count all matches.
* This method may choose to use {@link #estimatedCount(Class)} for empty queries instead of running an
* {@link com.mongodb.reactivestreams.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions)
* aggregation execution} which may have an impact on performance.
@@ -1041,6 +969,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
* @param collectionName must not be {@literal null} or empty.
* @return the count of matching documents.
* @see #count(Query, Class, String)
+ * @see #estimatedCount(String)
+ * @see #exactCount(Query, String)
*/
Mono count(Query query, String collectionName);
@@ -1050,8 +980,7 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
* NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
* 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.
- *
+ * count all matches.
* This method may choose to use {@link #estimatedCount(Class)} for empty queries instead of running an
* {@link com.mongodb.reactivestreams.client.MongoCollection#countDocuments(org.bson.conversions.Bson, com.mongodb.client.model.CountOptions)
* aggregation execution} which may have an impact on performance.
@@ -1061,6 +990,8 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
* @param entityClass the parametrized type. Can be {@literal null}.
* @param collectionName must not be {@literal null} or empty.
* @return the count of matching documents.
+ * @see #estimatedCount(String)
+ * @see #exactCount(Query, Class, String)
*/
Mono count(Query query, @Nullable Class> entityClass, String collectionName);
@@ -1093,6 +1024,75 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
*/
Mono estimatedCount(String collectionName);
+ /**
+ * Returns the number of documents for the given {@link Query} by querying the collection of the given entity class.
+ *
+ * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
+ * 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}.
+ * @param entityClass class that determines the collection to use. Must not be {@literal null}.
+ * @return the count of matching documents.
+ * @since 3.4
+ */
+ default Mono exactCount(Query query, Class> entityClass) {
+ return exactCount(query, entityClass, getCollectionName(entityClass));
+ }
+
+ /**
+ * Returns the number of documents for the given {@link Query} querying the given collection. The given {@link Query}
+ * must solely consist of document field references as we lack type information to map potential property references
+ * onto document fields. Use {@link #count(Query, Class, String)} to get full type specific support.
+ * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
+ * 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.
+ * @return the count of matching documents.
+ * @see #count(Query, Class, String)
+ * @since 3.4
+ */
+ default Mono exactCount(Query query, String collectionName) {
+ return exactCount(query, null, collectionName);
+ }
+
+ /**
+ * Returns the number of documents for the given {@link Query} by querying the given collection using the given entity
+ * class to map the given {@link Query}.
+ * NOTE: Query {@link Query#getSkip() offset} and {@link Query#getLimit() limit} can have direct
+ * 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}.
+ * @param entityClass the parametrized type. Can be {@literal null}.
+ * @param collectionName must not be {@literal null} or empty.
+ * @return the count of matching documents.
+ * @since 3.4
+ */
+ Mono exactCount(Query query, @Nullable Class> entityClass, String collectionName);
+
/**
* Insert the object into the collection for the entity type of the object to save.
*
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 49c6e075c..cfb3b9294 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
@@ -17,7 +17,6 @@ package org.springframework.data.mongodb.core;
import static org.springframework.data.mongodb.core.query.SerializationUtils.*;
-import org.springframework.data.projection.EntityProjection;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;
@@ -34,6 +33,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;
+import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -115,6 +115,7 @@ import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter;
import org.springframework.data.mongodb.core.timeseries.Granularity;
import org.springframework.data.mongodb.core.validation.Validator;
import org.springframework.data.mongodb.util.BsonUtils;
+import org.springframework.data.projection.EntityProjection;
import org.springframework.data.util.Optionals;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -358,8 +359,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
/**
* Set the {@link ReactiveEntityCallbacks} instance to use when invoking
* {@link org.springframework.data.mapping.callback.EntityCallback callbacks} like the
- * {@link ReactiveBeforeSaveCallback}.
- *
+ * {@link ReactiveBeforeSaveCallback}.
* Overrides potentially existing {@link ReactiveEntityCallbacks}.
*
* @param entityCallbacks must not be {@literal null}.
@@ -373,10 +373,10 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
}
/**
- * En-/Disable usage of estimated count.
+ * Configure whether to use estimated count. Defaults to exact counting.
*
- * @param enabled if {@literal true} {@link com.mongodb.client.MongoCollection#estimatedDocumentCount()} ()} will we used for unpaged,
- * empty {@link Query queries}.
+ * @param enabled use {@link com.mongodb.client.MongoCollection#estimatedDocumentCount()} for unpaged and empty
+ * {@link Query queries} if {@code true}.
* @since 3.4
*/
public void useEstimatedCount(boolean enabled) {
@@ -384,11 +384,11 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
}
/**
- * En-/Disable usage of estimated count based on the given {@link BiFunction estimationFilter}.
+ * Configure whether to use estimated count based on the given {@link BiPredicate estimationFilter}.
*
- * @param enabled if {@literal true} {@link com.mongodb.client.MongoCollection#estimatedDocumentCount()} will we used for {@link Document
- * filter queries} that pass the given {@link BiFunction estimationFilter}.
- * @param estimationFilter the {@link BiFunction filter}.
+ * @param enabled use {@link com.mongodb.client.MongoCollection#estimatedDocumentCount()} for unpaged and empty
+ * {@link Query queries} if {@code true}.
+ * @param estimationFilter the {@link BiPredicate filter}.
* @since 3.4
*/
private void useEstimatedCount(boolean enabled, BiFunction> estimationFilter) {
@@ -1098,8 +1098,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
String collection = StringUtils.hasText(collectionName) ? collectionName : getCollectionName(entityClass);
String distanceField = operations.nearQueryDistanceFieldName(entityClass);
- EntityProjection projection = operations.introspectProjection(returnType,
- entityClass);
+ EntityProjection projection = operations.introspectProjection(returnType, entityClass);
GeoNearResultDocumentCallback callback = new GeoNearResultDocumentCallback<>(distanceField,
new ProjectingReadCallback<>(mongoConverter, projection, collection), near.getMetric());
@@ -1181,8 +1180,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
MongoPersistentEntity> entity = mappingContext.getPersistentEntity(entityType);
QueryContext queryContext = queryOperations.createQueryContext(query);
- EntityProjection projection = operations.introspectProjection(resultType,
- entityType);
+ EntityProjection projection = operations.introspectProjection(resultType, entityType);
Document mappedQuery = queryContext.getMappedQuery(entity);
Document mappedFields = queryContext.getMappedFields(entity, projection);
@@ -1205,8 +1203,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
}).flatMap(it -> {
Mono afterFindAndReplace = doFindAndReplace(it.getCollection(), mappedQuery, mappedFields, mappedSort,
- queryContext.getCollation(entityType).orElse(null), entityType, it.getTarget(), options,
- projection);
+ queryContext.getCollation(entityType).orElse(null), entityType, it.getTarget(), options, projection);
return afterFindAndReplace.flatMap(saved -> {
maybeEmitEvent(new AfterSaveEvent<>(saved, it.getTarget(), it.getCollection()));
return maybeCallAfterSave(saved, it.getTarget(), it.getCollection());
@@ -1235,17 +1232,6 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
entityClass);
}
- @Override
- public Mono exactCount(Query query, @Nullable Class> entityClass, String collectionName) {
-
- CountContext countContext = queryOperations.countQueryContext(query);
-
- CountOptions options = countContext.getCountOptions(entityClass);
- Document mappedQuery = countContext.getMappedQuery(entityClass, mappingContext::getPersistentEntity);
-
- return doExactCount(collectionName, mappedQuery, options);
- }
-
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#count(org.springframework.data.mongodb.core.query.Query, java.lang.Class)
@@ -1290,15 +1276,6 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
});
}
- /*
- * (non-Javadoc)
- * @see org.springframework.data.mongodb.core.ReactiveMongoOperations#estimatedCount(java.lang.String)
- */
- @Override
- public Mono estimatedCount(String collectionName) {
- return doEstimatedCount(collectionName, new EstimatedDocumentCountOptions());
- }
-
/**
* Run the actual count operation against the collection with given name.
*
@@ -1317,19 +1294,39 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
return countExecution.countDocuments(collectionName, filter, options);
}
- protected Mono doExactCount(String collectionName, Document filter, CountOptions options) {
-
- return createMono(collectionName,
- collection -> collection.countDocuments(CountQuery.of(filter).toQueryDocument(), options));
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.mongodb.core.ReactiveMongoOperations#estimatedCount(java.lang.String)
+ */
+ @Override
+ public Mono estimatedCount(String collectionName) {
+ return doEstimatedCount(collectionName, new EstimatedDocumentCountOptions());
}
protected Mono doEstimatedCount(String collectionName, EstimatedDocumentCountOptions options) {
return createMono(collectionName, collection -> collection.estimatedDocumentCount(options));
}
+ @Override
+ public Mono exactCount(Query query, @Nullable Class> entityClass, String collectionName) {
+
+ CountContext countContext = queryOperations.countQueryContext(query);
+
+ CountOptions options = countContext.getCountOptions(entityClass);
+ Document mappedQuery = countContext.getMappedQuery(entityClass, mappingContext::getPersistentEntity);
+
+ return doExactCount(collectionName, mappedQuery, options);
+ }
+
+ protected Mono doExactCount(String collectionName, Document filter, CountOptions options) {
+
+ return createMono(collectionName,
+ collection -> collection.countDocuments(CountQuery.of(filter).toQueryDocument(), options));
+ }
+
protected Mono countCanBeEstimated(Document filter, CountOptions options) {
- if(!filter.isEmpty() || !isEmptyOptions(options)) {
+ if (!filter.isEmpty() || !isEmptyOptions(options)) {
return Mono.just(false);
}
return ReactiveMongoDatabaseUtils.isTransactionActive(getMongoDatabaseFactory()).map(it -> !it);
@@ -2450,8 +2447,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
QueryContext queryContext = queryOperations
.createQueryContext(new BasicQuery(query, fields != null ? fields : new Document()));
- Document mappedFields = queryContext.getMappedFields(entity,
- EntityProjection.nonProjecting(entityClass));
+ Document mappedFields = queryContext.getMappedFields(entity, EntityProjection.nonProjecting(entityClass));
Document mappedQuery = queryContext.getMappedQuery(entity);
if (LOGGER.isDebugEnabled()) {
@@ -2503,8 +2499,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
MongoPersistentEntity> entity = mappingContext.getPersistentEntity(entityClass);
QueryContext queryContext = queryOperations.createQueryContext(new BasicQuery(query, fields));
- Document mappedFields = queryContext.getMappedFields(entity,
- EntityProjection.nonProjecting(entityClass));
+ Document mappedFields = queryContext.getMappedFields(entity, EntityProjection.nonProjecting(entityClass));
Document mappedQuery = queryContext.getMappedQuery(entity);
if (LOGGER.isDebugEnabled()) {
@@ -2526,8 +2521,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
Class targetClass, FindPublisherPreparer preparer) {
MongoPersistentEntity> entity = mappingContext.getPersistentEntity(sourceClass);
- EntityProjection projection = operations.introspectProjection(targetClass,
- sourceClass);
+ EntityProjection projection = operations.introspectProjection(targetClass, sourceClass);
QueryContext queryContext = queryOperations.createQueryContext(new BasicQuery(query, fields));
Document mappedFields = queryContext.getMappedFields(entity, projection);
@@ -2602,8 +2596,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
/**
* Map the results of an ad-hoc query on the default MongoDB collection to an object using the template's converter.
- * The first document that matches the query is returned and also removed from the collection in the database.
- *
+ * The first document that matches the query is returned and also removed from the collection in the database.
* The query document is specified as a standard Document and so is the fields specification.
*
* @param collectionName name of the collection to retrieve the objects from
@@ -2674,8 +2667,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
Document mappedSort, com.mongodb.client.model.Collation collation, Class> entityType, Document replacement,
FindAndReplaceOptions options, Class resultType) {
- EntityProjection projection = operations.introspectProjection(resultType,
- entityType);
+ EntityProjection projection = operations.introspectProjection(resultType, entityType);
return doFindAndReplace(collectionName, mappedQuery, mappedFields, mappedSort, collation, entityType, replacement,
options, projection);
@@ -3298,8 +3290,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
private final EntityProjection projection;
private final String collectionName;
- ProjectingReadCallback(MongoConverter reader, EntityProjection projection,
- String collectionName) {
+ ProjectingReadCallback(MongoConverter reader, EntityProjection projection, String collectionName) {
this.reader = reader;
this.projection = projection;
this.collectionName = collectionName;
@@ -3476,8 +3467,7 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
/**
* {@link MongoTemplate} extension bound to a specific {@link ClientSession} that is applied when interacting with the
- * server through the driver API.
- *
+ * server through the driver API.
* The prepare steps for {@link MongoDatabase} and {@link MongoCollection} proxy the target and invoke the desired
* target method matching the actual arguments plus a {@link ClientSession}.
*