Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support comments on commands #140

Merged
merged 2 commits into from
Dec 6, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 26 additions & 29 deletions lib/mongo/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ def find_and_modify(opts={})
#
# @option opts [:primary, :secondary] :read Read preference indicating which server to perform this query
# on. See Collection#find for more details.
# @option opts [String] :comment (nil) a comment to include in profiling logs
#
# @return [Array] An Array with the aggregate command's results.
#
Expand All @@ -664,17 +665,11 @@ def aggregate(pipeline=nil, opts={})
raise MongoArgumentError, "pipeline must be an array of operators" unless pipeline.class == Array
raise MongoArgumentError, "pipeline operators must be hashes" unless pipeline.all? { |op| op.class == Hash }

if read_pref = opts[:read]
Mongo::Support.validate_read_preference(read_pref)
else
read_pref = read_preference
end

hash = BSON::OrderedHash.new
hash['aggregate'] = self.name
hash['pipeline'] = pipeline

result = @db.command(hash, :read => read_pref)
result = @db.command(hash, command_options(opts))
unless Mongo::Support.ok?(result)
raise Mongo::OperationFailure, "aggregate failed: #{result['errmsg']}"
end
Expand Down Expand Up @@ -706,6 +701,7 @@ def aggregate(pipeline=nil, opts={})
# or an ArgumentError will be raised.
# @option opts [:primary, :secondary] :read Read preference indicating which server to run this map-reduce
# on. See Collection#find for more details.
# @option opts [String] :comment (nil) a comment to include in profiling logs
#
# @return [Collection, Hash] a Mongo::Collection object or a Hash with the map-reduce command's results.
#
Expand All @@ -719,12 +715,6 @@ def map_reduce(map, reduce, opts={})
reduce = BSON::Code.new(reduce) unless reduce.is_a?(BSON::Code)
raw = opts.delete(:raw)

if read_pref = opts[:read]
Mongo::Support.validate_read_preference(read_pref)
else
read_pref = read_preference
end

hash = BSON::OrderedHash.new
hash['mapreduce'] = self.name
hash['map'] = map
Expand All @@ -734,7 +724,7 @@ def map_reduce(map, reduce, opts={})
hash[:sort] = Mongo::Support.format_order_clause(hash[:sort])
end

result = @db.command(hash, :read => read_pref)
result = @db.command(hash, command_options(opts))
unless Mongo::Support.ok?(result)
raise Mongo::OperationFailure, "map-reduce failed: #{result['errmsg']}"
end
Expand Down Expand Up @@ -771,6 +761,7 @@ def map_reduce(map, reduce, opts={})
# set to true.
# @option opts [:primary, :secondary] :read Read preference indicating which server to perform this group
# on. See Collection#find for more details.
# @option opts [String] :comment (nil) a comment to include in profiling logs
#
# @return [Array] the command response consisting of grouped items.
def group(opts, condition={}, initial={}, reduce=nil, finalize=nil)
Expand Down Expand Up @@ -836,12 +827,6 @@ def new_group(opts={})
raise MongoArgumentError, "Group requires at minimum values for initial and reduce."
end

if read_pref = opts[:read]
Mongo::Support.validate_read_preference(read_pref)
else
read_pref = read_preference
end

cmd = {
"group" => {
"ns" => @name,
Expand All @@ -866,7 +851,7 @@ def new_group(opts={})
cmd["group"]["$keyf"] = keyf.to_bson_code
end

result = @db.command(cmd, :read => read_pref)
result = @db.command(cmd, command_options(opts))
result["retval"]
end

Expand All @@ -882,6 +867,7 @@ def new_group(opts={})
#
# @option opts [:primary, :secondary] :read Read preference indicating which server to perform this query
# on. See Collection#find for more details.
# @option opts [String] :comment (nil) a comment to include in profiling logs
#
# @example Saving zip codes and ages and returning distinct results.
# @collection.save({:zip => 10010, :name => {:age => 27}})
Expand All @@ -908,13 +894,7 @@ def distinct(key, query=nil, opts={})
command[:key] = key.to_s
command[:query] = query

if read_pref = opts[:read]
Mongo::Support.validate_read_preference(read_pref)
else
read_pref = read_preference
end

@db.command(command, :read => read_pref)["values"]
@db.command(command, command_options(opts))["values"]
end

# Rename this collection.
Expand Down Expand Up @@ -981,19 +961,36 @@ def stats
# @option opts [Integer] :limit (nil) The number of documents to limit.
# @option opts [:primary, :secondary] :read Read preference for this command. See Collection#find for
# more details.
# @option opts [String] :comment (nil) a comment to include in profiling logs
#
# @return [Integer]
def count(opts={})
find(opts[:query],
:skip => opts[:skip],
:limit => opts[:limit],
:read => opts[:read]).count(true)
:read => opts[:read],
:comment => opts[:comment]).count(true)
end

alias :size :count

protected

# Parse common options for read-only commands from an input @opts
# hash and return a hash suitable for passing to DB#command.
def command_options(opts)
out = {}

if read_pref = opts[:read]
Mongo::Support.validate_read_preference(read_pref)
else
read_pref = read_preference
end
out[:read] = read_pref
out[:comment] = opts[:comment] if opts[:comment]
out
end

def normalize_hint_fields(hint)
case hint
when String
Expand Down
2 changes: 1 addition & 1 deletion lib/mongo/cursor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def count(skip_and_limit = false)

command.merge!(BSON::OrderedHash["fields", @fields])

response = @db.command(command, :read => @read_preference)
response = @db.command(command, :read => @read_preference, :comment => @comment)
return response['n'].to_i if Mongo::Support.ok?(response)
return 0 if response['errmsg'] == "ns missing"
raise OperationFailure.new("Count failed: #{response['errmsg']}", response['code'], response)
Expand Down
7 changes: 6 additions & 1 deletion lib/mongo/db.rb
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ def ok?(doc)
# @option opts [Socket] :socket a socket to use for sending the command. This is mainly for internal use.
# @option opts [:primary, :secondary] :read Read preference for this command. See Collection#find for
# more details.
# @option opts [String] :comment (nil) a comment to include in profiling logs
#
# @return [Hash]
#
Expand All @@ -535,7 +536,11 @@ def command(selector, opts={})

begin
result = Cursor.new(system_command_collection,
:limit => -1, :selector => selector, :socket => socket, :read => read_pref).next_document
:limit => -1,
:selector => selector,
:socket => socket,
:read => read_pref,
:comment => opts[:comment]).next_document
rescue OperationFailure => ex
raise OperationFailure, "Database command '#{selector.keys.first}' failed: #{ex.message}"
end
Expand Down
27 changes: 27 additions & 0 deletions test/unit/cursor_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,31 @@ class CursorTest < Test::Unit::TestCase
assert_nil @cursor.fields
end
end

context "counts" do
setup do
@logger = mock()
@logger.stubs(:debug)
@connection = stub(:class => Connection, :logger => @logger,
:slave_ok? => false, :read_preference => :primary, :log_duration => false,
:tag_sets => {}, :acceptable_latency => 10)
@db = stub(:name => "testing", :slave_ok? => false,
:connection => @connection, :read_preference => :primary,
:tag_sets => {}, :acceptable_latency => 10)
@collection = stub(:db => @db, :name => "items", :read_preference => :primary,
:tag_sets => {}, :acceptable_latency => 10)
@cursor = Cursor.new(@collection)
end

should "pass the comment parameter" do
query = {:field => 7}
@db.expects(:command).with({ 'count' => "items",
'query' => query,
'fields' => nil},
{ :read => :primary,
:comment => "my comment"}).
returns({'ok' => 1, 'n' => 1})
assert_equal(1, Cursor.new(@collection, :selector => query, :comment => 'my comment').count())
end
end
end
17 changes: 15 additions & 2 deletions test/unit/db_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,34 @@ class DBTest < Test::Unit::TestCase
should "create the proper cursor" do
@cursor = mock(:next_document => {"ok" => 1})
Cursor.expects(:new).with(@collection,
:limit => -1, :selector => {:buildinfo => 1}, :socket => nil, :read => nil).returns(@cursor)
:limit => -1, :selector => {:buildinfo => 1},
:socket => nil, :read => nil, :comment => nil).returns(@cursor)
command = {:buildinfo => 1}
@db.command(command, :check_response => true)
end

should "raise an error when the command fails" do
@cursor = mock(:next_document => {"ok" => 0})
Cursor.expects(:new).with(@collection,
:limit => -1, :selector => {:buildinfo => 1}, :socket => nil, :read => nil).returns(@cursor)
:limit => -1, :selector => {:buildinfo => 1},
:socket => nil, :read => nil, :comment => nil).returns(@cursor)
assert_raise OperationFailure do
command = {:buildinfo => 1}
@db.command(command, :check_response => true)
end
end

should "pass on the comment" do
@cursor = mock(:next_document => {"ok" => 0})
Cursor.expects(:new).with(@collection,
:limit => -1, :selector => {:buildinfo => 1},
:socket => nil, :read => nil, :comment => "my comment").returns(@cursor)
assert_raise OperationFailure do
command = {:buildinfo => 1}
@db.command(command, :check_response => true, :comment => 'my comment')
end
end

should "raise an error if logging out fails" do
@db.expects(:command).returns({})
@client.expects(:pool_size).returns(1)
Expand Down