diff --git a/README b/README index 35f5839..4f8a33f 100644 --- a/README +++ b/README @@ -57,8 +57,6 @@ type * Capped collection support. -* Implement order_by (right now, sort order is ignored) - * More code comments. More text in this file. * Support more types: REF, SYMBOL, CODE_W_SCOPE, etc. diff --git a/lib/mongo/cursor.rb b/lib/mongo/cursor.rb index 0ea1b07..329fb5c 100644 --- a/lib/mongo/cursor.rb +++ b/lib/mongo/cursor.rb @@ -39,7 +39,9 @@ module XGen def next_object refill_via_get_more if num_remaining == 0 - @objects.shift + o = @objects.shift + raise o['$err'] if o['$err'] + o end def each diff --git a/lib/mongo/message/query_message.rb b/lib/mongo/message/query_message.rb index c2bb5b1..477822e 100644 --- a/lib/mongo/message/query_message.rb +++ b/lib/mongo/message/query_message.rb @@ -1,5 +1,6 @@ require 'mongo/message/message' require 'mongo/message/opcodes' +require 'mongo/util/ordered_hash' module XGen module Mongo @@ -13,7 +14,30 @@ module XGen write_string("#{db_name}.#{collection_name}") write_int(query.number_to_skip) write_int(query.number_to_return) - write_doc(query.selector) + sel = query.selector + if query.order_by + sel = OrderedHash.new + sel['query'] = query.selector + sel['orderby'] = case query.order_by + when Array + if query.order_by.empty? # Empty array of order_by values + [] + else + case query.order_by[0] + when Hash # Array of hashes + query.order_by + else # ['a', 'b'] + query.order_by.collect { |v| {v => 1} } # Assume ascending order for all values + end + end + when Hash # Should be an ordered hash, but this message doesn't care + a = [] + query.order_by.each { |k,v| a << {k => v }} + a + end + + end + write_doc(sel) write_doc(query.fields) if query.fields end diff --git a/tests/test_db_api.rb b/tests/test_db_api.rb index a063848..a2f173f 100644 --- a/tests/test_db_api.rb +++ b/tests/test_db_api.rb @@ -124,16 +124,30 @@ class DBAPITest < Test::Unit::TestCase @coll.insert('b' => 3) # Sorting (ascending) - order_by = OrderedHash.new - order_by['a'] = 1 - docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => order_by).map + docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => [{'a' => 1}]).map assert_equal 2, docs.size assert_equal 1, docs.first['a'] # Sorting (descending) - order_by = OrderedHash.new - order_by['a'] = -1 - docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => order_by).map + docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => [{'a' => -1}]).map + assert_equal 2, docs.size + assert_equal 2, docs.first['a'] + + # Sorting using array of names; assumes ascending order + # NOTE: Mongo itself does not yet properly sort by multiple names + docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => ['a']).map + assert_equal 2, docs.size + assert_equal 1, docs.first['a'] + + # Sorting using empty array; no order guarantee but should not blow up. + docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => [{'a' => -1}]).map + assert_equal 2, docs.size + + # Sorting using ordered hash. You can use an unordered one, but then the + # order of the keys won't be guaranteed thus your sort won't make sense. + oh = OrderedHash.new + oh['a'] = -1 + docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => oh).map assert_equal 2, docs.size assert_equal 2, docs.first['a'] end