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 bb6c402fb..b1c5d3ee4 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
@@ -1184,6 +1184,29 @@ public interface MongoOperations extends FluentMongoOperations {
*/
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.
+ *
+ * @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.
+ *
+ * @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}.
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 d1f1790c7..91242611b 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
@@ -1134,6 +1134,19 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware,
collection -> collection.countDocuments(CountQuery.of(filter).toQueryDocument(), 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));
+ }
+
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.MongoOperations#insert(java.lang.Object)
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 9bf4514b3..94fc8843f 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
@@ -980,6 +980,29 @@ public interface ReactiveMongoOperations extends ReactiveFluentMongoOperations {
*/
Mono 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.
+ *
+ * @param entityClass must not be {@literal null}.
+ * @return a {@link Mono} emitting the estimated number of documents.
+ * @since 3.1
+ */
+ default Mono 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.
+ *
+ * @param collectionName must not be {@literal null}.
+ * @return a {@link Mono} emitting the estimated number of documents.
+ * @since 3.1
+ */
+ Mono estimatedCount(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 532ea54aa..336010434 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,6 +17,7 @@ package org.springframework.data.mongodb.core;
import static org.springframework.data.mongodb.core.query.SerializationUtils.*;
+import com.mongodb.client.model.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;
@@ -116,16 +117,6 @@ import com.mongodb.CursorType;
import com.mongodb.MongoException;
import com.mongodb.ReadPreference;
import com.mongodb.WriteConcern;
-import com.mongodb.client.model.CountOptions;
-import com.mongodb.client.model.CreateCollectionOptions;
-import com.mongodb.client.model.DeleteOptions;
-import com.mongodb.client.model.FindOneAndDeleteOptions;
-import com.mongodb.client.model.FindOneAndReplaceOptions;
-import com.mongodb.client.model.FindOneAndUpdateOptions;
-import com.mongodb.client.model.ReplaceOptions;
-import com.mongodb.client.model.ReturnDocument;
-import com.mongodb.client.model.UpdateOptions;
-import com.mongodb.client.model.ValidationOptions;
import com.mongodb.client.model.changestream.FullDocument;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.InsertOneResult;
@@ -1247,6 +1238,15 @@ 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.
*
@@ -1261,6 +1261,12 @@ public class ReactiveMongoTemplate implements ReactiveMongoOperations, Applicati
collection -> collection.countDocuments(CountQuery.of(filter).toQueryDocument(), options));
}
+ protected Mono doEstimatedCount(String collectionName, EstimatedDocumentCountOptions options) {
+
+ return createMono(collectionName,
+ collection -> collection.estimatedDocumentCount(options));
+ }
+
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.ReactiveMongoOperations#insert(reactor.core.publisher.Mono)
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java
index 28f374d2b..f5cddf9d8 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java
@@ -177,6 +177,7 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
when(collection.mapReduce(any(), any(), eq(Document.class))).thenReturn(mapReduceIterable);
when(collection.countDocuments(any(Bson.class), any(CountOptions.class))).thenReturn(1L); // TODO: MongoDB 4 - fix
// me
+ when(collection.estimatedDocumentCount(any())).thenReturn(1L);
when(collection.getNamespace()).thenReturn(new MongoNamespace("db.mock-collection"));
when(collection.aggregate(any(List.class), any())).thenReturn(aggregateIterable);
when(collection.withReadPreference(any())).thenReturn(collection);
@@ -2153,6 +2154,15 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
assertThat(saved.id).isEqualTo("after-save-event");
}
+ @Test // DATAMONGO-2556
+ void esitmatedCountShouldBeDelegatedCorrectly() {
+
+ template.estimatedCount(Person.class);
+
+ verify(db).getCollection("star-wars", Document.class);
+ verify(collection).estimatedDocumentCount(any());
+ }
+
class AutogenerateableId {
@Id BigInteger id;
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java
index 46073a895..bd310e872 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateUnitTests.java
@@ -158,6 +158,7 @@ public class ReactiveMongoTemplateUnitTests {
when(collection.aggregate(anyList())).thenReturn(aggregatePublisher);
when(collection.aggregate(anyList(), any(Class.class))).thenReturn(aggregatePublisher);
when(collection.countDocuments(any(), any(CountOptions.class))).thenReturn(Mono.just(0L));
+ when(collection.estimatedDocumentCount(any())).thenReturn(Mono.just(0L));
when(collection.updateOne(any(), any(Bson.class), any(UpdateOptions.class))).thenReturn(updateResultPublisher);
when(collection.updateMany(any(Bson.class), any(Bson.class), any())).thenReturn(updateResultPublisher);
when(collection.updateOne(any(), anyList(), any())).thenReturn(updateResultPublisher);
@@ -1365,6 +1366,15 @@ public class ReactiveMongoTemplateUnitTests {
assertThat(saved.id).isEqualTo("after-save-event");
}
+ @Test // DATAMONGO-2556
+ void esitmatedCountShouldBeDelegatedCorrectly() {
+
+ template.estimatedCount(Person.class).subscribe();
+
+ verify(db).getCollection("star-wars", Document.class);
+ verify(collection).estimatedDocumentCount(any());
+ }
+
private void stubFindSubscribe(Document document) {
Publisher realPublisher = Flux.just(document);