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