@@ -230,24 +230,46 @@ def estimated_document_count(opts = {})
230230 raise ArgumentError , "Cannot call estimated_document_count when querying with a filter"
231231 end
232232
233- cmd = { count : collection . name }
234- cmd [ :maxTimeMS ] = opts [ :max_time_ms ] if opts [ :max_time_ms ]
235- if read_concern
236- cmd [ :readConcern ] = Options ::Mapper . transform_values_to_strings (
237- read_concern )
238- end
239233 Mongo ::Lint . validate_underscore_read_preference ( opts [ :read ] )
240234 read_pref = opts [ :read ] || read_preference
241235 selector = ServerSelector . get ( read_pref || server_selector )
242236 with_session ( opts ) do |session |
237+ context = Operation ::Context . new ( client : client , session : session )
243238 read_with_retry ( session , selector ) do |server |
244- Operation ::Count . new (
245- selector : cmd ,
246- db_name : database . name ,
247- read : read_pref ,
248- session : session ,
249- ) . execute ( server , context : Operation ::Context . new ( client : client , session : session ) )
250- end . n . to_i
239+ if server . description . server_version_gte? ( '5.0' )
240+ pipeline = [
241+ { '$collStats' => { 'count' => { } } } ,
242+ { '$group' => { '_id' => 1 , 'n' => { '$sum' => '$count' } } } ,
243+ ]
244+ spec = Builder ::Aggregation . new ( pipeline , self , options . merge ( session : session ) ) . specification
245+ result = Operation ::Aggregate . new ( spec ) . execute ( server , context : context )
246+ result . documents . first . fetch ( 'n' )
247+ else
248+ cmd = { count : collection . name }
249+ cmd [ :maxTimeMS ] = opts [ :max_time_ms ] if opts [ :max_time_ms ]
250+ if read_concern
251+ cmd [ :readConcern ] = Options ::Mapper . transform_values_to_strings (
252+ read_concern )
253+ end
254+ result = Operation ::Count . new (
255+ selector : cmd ,
256+ db_name : database . name ,
257+ read : read_pref ,
258+ session : session ,
259+ ) . execute ( server , context : context )
260+ result . n . to_i
261+ end
262+ end
263+ end
264+ rescue Error ::OperationFailure => exc
265+ if exc . code == 26
266+ # NamespaceNotFound
267+ # This should only happen with the aggregation pipeline path
268+ # (server 4.9+). Previous servers should return 0 for nonexistent
269+ # collections.
270+ 0
271+ else
272+ raise
251273 end
252274 end
253275
0 commit comments