lib/mongo/collection/view/readable.rb in mongo-2.14.1 vs lib/mongo/collection/view/readable.rb in mongo-2.15.0.alpha

- old
+ new

@@ -170,12 +170,12 @@ Operation::Count.new( :selector => cmd, :db_name => database.name, :options => {:limit => -1}, :read => read_pref, - :session => session - ).execute(server, client: client) + :session => session, + ).execute(server, context: Operation::Context.new(client: client, session: session)) end.n.to_i end end # Get a count of matching documents in the collection. @@ -228,29 +228,51 @@ def estimated_document_count(opts = {}) unless view.filter.empty? raise ArgumentError, "Cannot call estimated_document_count when querying with a filter" end - cmd = { count: collection.name } - cmd[:maxTimeMS] = opts[:max_time_ms] if opts[:max_time_ms] - if read_concern - cmd[:readConcern] = Options::Mapper.transform_values_to_strings( - read_concern) - end Mongo::Lint.validate_underscore_read_preference(opts[:read]) read_pref = opts[:read] || read_preference selector = ServerSelector.get(read_pref || server_selector) with_session(opts) do |session| + context = Operation::Context.new(client: client, session: session) read_with_retry(session, selector) do |server| - Operation::Count.new( - selector: cmd, - db_name: database.name, - read: read_pref, - session: session - ).execute(server, client: client) - end.n.to_i + if server.description.server_version_gte?('5.0') + pipeline = [ + {'$collStats' => {'count' => {}}}, + {'$group' => {'_id' => 1, 'n' => {'$sum' => '$count'}}}, + ] + spec = Builder::Aggregation.new(pipeline, self, options.merge(session: session)).specification + result = Operation::Aggregate.new(spec).execute(server, context: context) + result.documents.first.fetch('n') + else + cmd = { count: collection.name } + cmd[:maxTimeMS] = opts[:max_time_ms] if opts[:max_time_ms] + if read_concern + cmd[:readConcern] = Options::Mapper.transform_values_to_strings( + read_concern) + end + result = Operation::Count.new( + selector: cmd, + db_name: database.name, + read: read_pref, + session: session, + ).execute(server, context: context) + result.n.to_i + end + end end + rescue Error::OperationFailure => exc + if exc.code == 26 + # NamespaceNotFound + # This should only happen with the aggregation pipeline path + # (server 4.9+). Previous servers should return 0 for nonexistent + # collections. + 0 + else + raise + end end # Get a list of distinct values for a specific field. # # @example Get the distinct values. @@ -288,12 +310,12 @@ Operation::Distinct.new({ :selector => cmd, :db_name => database.name, :options => {:limit => -1}, :read => read_pref, - :session => session - }).execute(server, client: client) + :session => session, + }).execute(server, context: Operation::Context.new(client: client, session: session)) end.first['values'] end end # The index that MongoDB will be forced to use for the query. @@ -624,24 +646,24 @@ :db_name => database.name, :cursor_count => cursor_count, :read_concern => read_concern, :session => session, }.merge!(options)) - cmd.execute(server, client: client).cursor_ids.map do |cursor_id| + cmd.execute(server, context: Operation::Context.new(client: client, session: session)).cursor_ids.map do |cursor_id| result = if server.with_connection { |connection| connection.features }.find_command_enabled? Operation::GetMore.new({ :selector => {:getMore => BSON::Int64.new(cursor_id), :collection => collection.name}, :db_name => database.name, :session => session, - }).execute(server, client: client) + }).execute(server, context: Operation::Context.new(client: client, session: session)) else Operation::GetMore.new({ :to_return => 0, :cursor_id => BSON::Int64.new(cursor_id), :db_name => database.name, :coll_name => collection.name - }).execute(server, client: client) + }).execute(server, context: Operation::Context.new(client: client, session: session)) end Cursor.new(self, result, server, session: session) end end