@@ -796,6 +796,56 @@ mongoc_collection_count_with_opts (
796
796
RETURN (ret );
797
797
}
798
798
799
+ /* --------------------------------------------------------------------------
800
+ *
801
+ * _make_aggregate_for_edc --
802
+ *
803
+ * Construct an aggregate pipeline with the following form:
804
+ *
805
+ *
806
+ * { pipeline: [
807
+ * { $collStats: { count: {} } },
808
+ * { $group: { _id: 1, n: { $sum: $count } } },
809
+ * ]
810
+ * }
811
+ *
812
+ *--------------------------------------------------------------------------
813
+ */
814
+ static void
815
+ _make_aggregate_for_edc (const mongoc_collection_t * coll , bson_t * out )
816
+ {
817
+ bson_t pipeline ;
818
+ bson_t coll_stats_stage ;
819
+ bson_t coll_stats_stage_doc ;
820
+ bson_t group_stage ;
821
+ bson_t group_stage_doc ;
822
+ bson_t sum ;
823
+ bson_t cursor_empty ;
824
+ bson_t empty ;
825
+
826
+ BSON_APPEND_UTF8 (out , "aggregate" , coll -> collection );
827
+ BSON_APPEND_DOCUMENT_BEGIN (out , "cursor" , & cursor_empty );
828
+ bson_append_document_end (out , & cursor_empty );
829
+ BSON_APPEND_ARRAY_BEGIN (out , "pipeline" , & pipeline );
830
+
831
+ BSON_APPEND_DOCUMENT_BEGIN (& pipeline , "0" , & coll_stats_stage );
832
+ BSON_APPEND_DOCUMENT_BEGIN (
833
+ & coll_stats_stage , "$collStats" , & coll_stats_stage_doc );
834
+ BSON_APPEND_DOCUMENT_BEGIN (& coll_stats_stage_doc , "count" , & empty );
835
+ bson_append_document_end (& coll_stats_stage_doc , & empty );
836
+ bson_append_document_end (& coll_stats_stage , & coll_stats_stage_doc );
837
+ bson_append_document_end (& pipeline , & coll_stats_stage );
838
+
839
+ BSON_APPEND_DOCUMENT_BEGIN (& pipeline , "1" , & group_stage );
840
+ BSON_APPEND_DOCUMENT_BEGIN (& group_stage , "$group" , & group_stage_doc );
841
+ BSON_APPEND_INT32 (& group_stage_doc , "_id" , 1 );
842
+ BSON_APPEND_DOCUMENT_BEGIN (& group_stage_doc , "n" , & sum );
843
+ BSON_APPEND_UTF8 (& sum , "$sum" , "$count" );
844
+ bson_append_document_end (& group_stage_doc , & sum );
845
+ bson_append_document_end (& group_stage , & group_stage_doc );
846
+ bson_append_document_end (& pipeline , & group_stage );
847
+ bson_append_array_end (out , & pipeline );
848
+ }
799
849
800
850
int64_t
801
851
mongoc_collection_estimated_document_count (
@@ -811,11 +861,15 @@ mongoc_collection_estimated_document_count (
811
861
bson_t reply_local ;
812
862
bson_t * reply_ptr ;
813
863
bson_t cmd = BSON_INITIALIZER ;
864
+ mongoc_server_stream_t * server_stream = NULL ;
814
865
815
866
ENTRY ;
816
867
817
868
BSON_ASSERT_PARAM (coll );
818
869
870
+ server_stream = mongoc_cluster_stream_for_reads (
871
+ & coll -> client -> cluster , read_prefs , NULL , reply , error );
872
+
819
873
if (opts && bson_has_field (opts , "sessionId" )) {
820
874
bson_set_error (error ,
821
875
MONGOC_ERROR_COMMAND ,
@@ -825,24 +879,45 @@ mongoc_collection_estimated_document_count (
825
879
}
826
880
827
881
reply_ptr = reply ? reply : & reply_local ;
828
- bson_append_utf8 (& cmd , "count" , 5 , coll -> collection , coll -> collectionlen );
829
-
830
- ret = _mongoc_client_command_with_opts (coll -> client ,
831
- coll -> db ,
832
- & cmd ,
833
- MONGOC_CMD_READ ,
834
- opts ,
835
- MONGOC_QUERY_NONE ,
836
- read_prefs ,
837
- coll -> read_prefs ,
838
- coll -> read_concern ,
839
- coll -> write_concern ,
840
- reply_ptr ,
841
- error );
842
-
843
- if (ret ) {
844
- if (bson_iter_init_find (& iter , reply_ptr , "n" )) {
845
- count = bson_iter_as_int64 (& iter );
882
+ if (server_stream -> sd -> max_wire_version < WIRE_VERSION_4_9 ) {
883
+ /* On < 4.9, use actual count command for estimatedDocumentCount */
884
+ BSON_APPEND_UTF8 (& cmd , "count" , coll -> collection );
885
+ ret = _mongoc_client_command_with_opts (coll -> client ,
886
+ coll -> db ,
887
+ & cmd ,
888
+ MONGOC_CMD_READ ,
889
+ opts ,
890
+ MONGOC_QUERY_NONE ,
891
+ read_prefs ,
892
+ coll -> read_prefs ,
893
+ coll -> read_concern ,
894
+ coll -> write_concern ,
895
+ reply_ptr ,
896
+ error );
897
+ if (ret ) {
898
+ if (bson_iter_init_find (& iter , reply_ptr , "n" )) {
899
+ count = bson_iter_as_int64 (& iter );
900
+ }
901
+ }
902
+ } else {
903
+ /* On >= 4.9, use aggregate with collStats for estimatedDocumentCount */
904
+ _make_aggregate_for_edc (coll , & cmd );
905
+ ret = mongoc_collection_read_command_with_opts (
906
+ coll , & cmd , read_prefs , opts , reply_ptr , error );
907
+
908
+ if (error && error -> code == MONGOC_ERROR_COLLECTION_DOES_NOT_EXIST ) {
909
+ /* Collection does not exist. From spec: return 0 but no err:
910
+ * https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#estimateddocumentcount
911
+ */
912
+ memset (error , 0 , sizeof * error );
913
+ count = 0 ;
914
+ GOTO (done );
915
+ }
916
+ if (ret && bson_iter_init (& iter , reply_ptr )) {
917
+ if (bson_iter_find_descendant (
918
+ & iter , "cursor.firstBatch.0.n" , & iter )) {
919
+ count = bson_iter_as_int64 (& iter );
920
+ }
846
921
}
847
922
}
848
923
@@ -851,6 +926,7 @@ mongoc_collection_estimated_document_count (
851
926
bson_destroy (& reply_local );
852
927
}
853
928
bson_destroy (& cmd );
929
+ mongoc_server_stream_cleanup (server_stream );
854
930
855
931
RETURN (count );
856
932
}
@@ -3380,9 +3456,8 @@ mongoc_collection_find_and_modify_with_opts (
3380
3456
retry_server_stream = mongoc_cluster_stream_for_writes (
3381
3457
cluster , parts .assembled .session , NULL /* reply */ , & ignored_error );
3382
3458
3383
- if (retry_server_stream &&
3384
- retry_server_stream -> sd -> max_wire_version >=
3385
- WIRE_VERSION_RETRY_WRITES ) {
3459
+ if (retry_server_stream && retry_server_stream -> sd -> max_wire_version >=
3460
+ WIRE_VERSION_RETRY_WRITES ) {
3386
3461
parts .assembled .server_stream = retry_server_stream ;
3387
3462
GOTO (retry );
3388
3463
}
0 commit comments