mongo 0.19.1 → 0.19.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +14 -14
- data/Rakefile +5 -0
- data/bin/gr.rb +14 -0
- data/lib/bson.rb +46 -0
- data/lib/bson/bson_c.rb +20 -0
- data/lib/bson/bson_ruby.rb +601 -0
- data/lib/bson/byte_buffer.rb +224 -0
- data/lib/bson/exceptions.rb +39 -0
- data/lib/bson/ordered_hash.rb +140 -0
- data/lib/bson/types/binary.rb +54 -0
- data/lib/bson/types/code.rb +36 -0
- data/lib/bson/types/dbref.rb +40 -0
- data/lib/bson/types/min_max_keys.rb +58 -0
- data/lib/bson/types/objectid.rb +180 -0
- data/lib/bson/types/regexp_of_holding.rb +45 -0
- data/lib/mongo.rb +4 -2
- data/lib/mongo/collection.rb +61 -20
- data/lib/mongo/connection.rb +18 -4
- data/lib/mongo/cursor.rb +13 -12
- data/lib/mongo/db.rb +11 -29
- data/lib/mongo/gridfs/grid.rb +1 -1
- data/lib/mongo/gridfs/grid_io.rb +4 -0
- data/lib/mongo/util/core_ext.rb +37 -0
- data/lib/mongo/util/support.rb +40 -7
- data/test/auxillary/1.4_features.rb +166 -0
- data/test/collection_test.rb +30 -1
- data/test/connection_test.rb +18 -1
- data/test/cursor_test.rb +14 -0
- data/test/db_api_test.rb +4 -10
- data/test/grid_test.rb +13 -0
- data/test/unit/collection_test.rb +14 -4
- metadata +27 -5
data/lib/mongo/connection.rb
CHANGED
@@ -276,19 +276,33 @@ module Mongo
|
|
276
276
|
self[name].command(:dropDatabase => 1)
|
277
277
|
end
|
278
278
|
|
279
|
-
# Copy the database +from+
|
280
|
-
#
|
279
|
+
# Copy the database +from+ to +to+ on localhost. The +from+ database is
|
280
|
+
# assumed to be on localhost, but an alternate host can be specified.
|
281
281
|
#
|
282
282
|
# @param [String] from name of the database to copy from.
|
283
283
|
# @param [String] to name of the database to copy to.
|
284
284
|
# @param [String] from_host host of the 'from' database.
|
285
|
-
|
285
|
+
# @param [String] username username for authentication against from_db (>=1.3.x).
|
286
|
+
# @param [String] password password for authentication against from_db (>=1.3.x).
|
287
|
+
def copy_database(from, to, from_host="localhost", username=nil, password=nil)
|
286
288
|
oh = OrderedHash.new
|
287
289
|
oh[:copydb] = 1
|
288
290
|
oh[:fromhost] = from_host
|
289
291
|
oh[:fromdb] = from
|
290
292
|
oh[:todb] = to
|
291
|
-
|
293
|
+
if username || password
|
294
|
+
unless username && password
|
295
|
+
raise MongoArgumentError, "Both username and password must be supplied for authentication."
|
296
|
+
end
|
297
|
+
nonce_cmd = OrderedHash.new
|
298
|
+
nonce_cmd[:copydbgetnonce] = 1
|
299
|
+
nonce_cmd[:fromhost] = from_host
|
300
|
+
result = self["admin"].command(nonce_cmd, true, true)
|
301
|
+
oh[:nonce] = result["nonce"]
|
302
|
+
oh[:username] = username
|
303
|
+
oh[:key] = Mongo::Support.auth_key(username, password, oh[:nonce])
|
304
|
+
end
|
305
|
+
self["admin"].command(oh, true, true)
|
292
306
|
end
|
293
307
|
|
294
308
|
# Increment and return the next available request id.
|
data/lib/mongo/cursor.rb
CHANGED
@@ -78,6 +78,13 @@ module Mongo
|
|
78
78
|
doc
|
79
79
|
end
|
80
80
|
|
81
|
+
# Determine whether this cursor has any remaining results.
|
82
|
+
#
|
83
|
+
# @return [Boolean]
|
84
|
+
def has_next?
|
85
|
+
num_remaining > 0
|
86
|
+
end
|
87
|
+
|
81
88
|
# Get the size of the result set for this query.
|
82
89
|
#
|
83
90
|
# @return [Integer] the number of objects in the result set for this query. Does
|
@@ -169,7 +176,7 @@ module Mongo
|
|
169
176
|
# end
|
170
177
|
def each
|
171
178
|
num_returned = 0
|
172
|
-
while
|
179
|
+
while has_next? && (@limit <= 0 || num_returned < @limit)
|
173
180
|
yield next_document
|
174
181
|
num_returned += 1
|
175
182
|
end
|
@@ -188,7 +195,7 @@ module Mongo
|
|
188
195
|
raise InvalidOperation, "can't call Cursor#to_a on a used cursor" if @query_run
|
189
196
|
rows = []
|
190
197
|
num_returned = 0
|
191
|
-
while
|
198
|
+
while has_next? && (@limit <= 0 || num_returned < @limit)
|
192
199
|
rows << next_document
|
193
200
|
num_returned += 1
|
194
201
|
end
|
@@ -223,7 +230,7 @@ module Mongo
|
|
223
230
|
message = ByteBuffer.new([0, 0, 0, 0])
|
224
231
|
message.put_int(1)
|
225
232
|
message.put_long(@cursor_id)
|
226
|
-
@connection.send_message(Mongo::Constants::OP_KILL_CURSORS, message, "cursor.close
|
233
|
+
@connection.send_message(Mongo::Constants::OP_KILL_CURSORS, message, "cursor.close")
|
227
234
|
end
|
228
235
|
@cursor_id = 0
|
229
236
|
@closed = true
|
@@ -305,13 +312,6 @@ module Mongo
|
|
305
312
|
@cache.length
|
306
313
|
end
|
307
314
|
|
308
|
-
# Internal method, not for general use. Return +true+ if there are
|
309
|
-
# more records to retrieve. This method does not check @limit;
|
310
|
-
# Cursor#each is responsible for doing that.
|
311
|
-
def more?
|
312
|
-
num_remaining > 0
|
313
|
-
end
|
314
|
-
|
315
315
|
def refill_via_get_more
|
316
316
|
return if send_initial_query || @cursor_id.zero?
|
317
317
|
message = ByteBuffer.new([0, 0, 0, 0])
|
@@ -362,8 +362,9 @@ module Mongo
|
|
362
362
|
end
|
363
363
|
|
364
364
|
def query_log_message
|
365
|
-
"#{@admin ? 'admin' : @db.name}
|
366
|
-
"#{@skip != 0 ? ('.skip(' + @skip.to_s + ')') : ''}#{@limit != 0 ? ('.limit(' + @limit.to_s + ')') : ''}"
|
365
|
+
"#{@admin ? 'admin' : @db.name}['#{@collection.name}'].find(#{@selector.inspect}, #{@fields ? @fields.inspect : '{}'})" +
|
366
|
+
"#{@skip != 0 ? ('.skip(' + @skip.to_s + ')') : ''}#{@limit != 0 ? ('.limit(' + @limit.to_s + ')') : ''}" +
|
367
|
+
"#{@order ? ('.sort(' + @order.inspect + ')') : ''}"
|
367
368
|
end
|
368
369
|
|
369
370
|
def selector_with_special_query_fields
|
data/lib/mongo/db.rb
CHANGED
@@ -16,7 +16,6 @@
|
|
16
16
|
|
17
17
|
require 'socket'
|
18
18
|
require 'timeout'
|
19
|
-
require 'digest/md5'
|
20
19
|
require 'thread'
|
21
20
|
|
22
21
|
module Mongo
|
@@ -65,7 +64,7 @@ module Mongo
|
|
65
64
|
#
|
66
65
|
# @core databases constructor_details
|
67
66
|
def initialize(db_name, connection, options={})
|
68
|
-
@name = validate_db_name(db_name)
|
67
|
+
@name = Mongo::Support.validate_db_name(db_name)
|
69
68
|
@connection = connection
|
70
69
|
@strict = options[:strict]
|
71
70
|
@pk_factory = options[:pk]
|
@@ -94,7 +93,7 @@ module Mongo
|
|
94
93
|
auth['authenticate'] = 1
|
95
94
|
auth['user'] = username
|
96
95
|
auth['nonce'] = nonce
|
97
|
-
auth['key'] =
|
96
|
+
auth['key'] = Mongo::Support.auth_key(username, password, nonce)
|
98
97
|
if ok?(command(auth))
|
99
98
|
if save_auth
|
100
99
|
@connection.add_auth(@name, username, password)
|
@@ -115,7 +114,7 @@ module Mongo
|
|
115
114
|
def add_user(username, password)
|
116
115
|
users = self[SYSTEM_USER_COLLECTION]
|
117
116
|
user = users.find_one({:user => username}) || {:user => username}
|
118
|
-
user['pwd'] = hash_password(username, password)
|
117
|
+
user['pwd'] = Mongo::Support.hash_password(username, password)
|
119
118
|
users.save(user)
|
120
119
|
return user
|
121
120
|
end
|
@@ -379,11 +378,11 @@ module Mongo
|
|
379
378
|
# @return [Hash] keys are index names and the values are lists of [key, direction] pairs
|
380
379
|
# defining the index.
|
381
380
|
def index_information(collection_name)
|
382
|
-
sel
|
381
|
+
sel = {:ns => full_collection_name(collection_name)}
|
383
382
|
info = {}
|
384
|
-
Cursor.new(Collection.new(self, SYSTEM_INDEX_COLLECTION), :selector => sel).each
|
385
|
-
info[index['name']] = index
|
386
|
-
|
383
|
+
Cursor.new(Collection.new(self, SYSTEM_INDEX_COLLECTION), :selector => sel).each do |index|
|
384
|
+
info[index['name']] = index
|
385
|
+
end
|
387
386
|
info
|
388
387
|
end
|
389
388
|
|
@@ -416,8 +415,9 @@ module Mongo
|
|
416
415
|
# Note: DB commands must start with the "command" key. For this reason,
|
417
416
|
# any selector containing more than one key must be an OrderedHash.
|
418
417
|
#
|
419
|
-
#
|
420
|
-
# that occurs on the system command collection ($cmd).
|
418
|
+
# Note also that a command in MongoDB is just a kind of query
|
419
|
+
# that occurs on the system command collection ($cmd). Examine this method's implementation
|
420
|
+
# to see how it works.
|
421
421
|
#
|
422
422
|
# @param [OrderedHash, Hash] selector an OrderedHash, or a standard Hash with just one
|
423
423
|
# key, specifying the command to be performed.
|
@@ -443,7 +443,7 @@ module Mongo
|
|
443
443
|
:limit => -1, :selector => selector, :socket => sock).next_document
|
444
444
|
|
445
445
|
if check_response && !ok?(result)
|
446
|
-
raise OperationFailure, "Database command '#{selector.keys.first}' failed."
|
446
|
+
raise OperationFailure, "Database command '#{selector.keys.first}' failed: #{result.inspect}"
|
447
447
|
else
|
448
448
|
result
|
449
449
|
end
|
@@ -545,26 +545,8 @@ module Mongo
|
|
545
545
|
|
546
546
|
private
|
547
547
|
|
548
|
-
def hash_password(username, plaintext)
|
549
|
-
Digest::MD5.hexdigest("#{username}:mongo:#{plaintext}")
|
550
|
-
end
|
551
|
-
|
552
548
|
def system_command_collection
|
553
549
|
Collection.new(self, SYSTEM_COMMAND_COLLECTION)
|
554
550
|
end
|
555
|
-
|
556
|
-
def validate_db_name(db_name)
|
557
|
-
unless [String, Symbol].include?(db_name.class)
|
558
|
-
raise TypeError, "db_name must be a string or symbol"
|
559
|
-
end
|
560
|
-
|
561
|
-
[" ", ".", "$", "/", "\\"].each do |invalid_char|
|
562
|
-
if db_name.include? invalid_char
|
563
|
-
raise InvalidName, "database names cannot contain the character '#{invalid_char}'"
|
564
|
-
end
|
565
|
-
end
|
566
|
-
raise InvalidName, "database name cannot be the empty string" if db_name.empty?
|
567
|
-
db_name
|
568
|
-
end
|
569
551
|
end
|
570
552
|
end
|
data/lib/mongo/gridfs/grid.rb
CHANGED
data/lib/mongo/gridfs/grid_io.rb
CHANGED
@@ -78,6 +78,7 @@ module Mongo
|
|
78
78
|
# @return [String]
|
79
79
|
# the data in the file
|
80
80
|
def read(length=nil)
|
81
|
+
return '' if @file_length.zero?
|
81
82
|
if length == 0
|
82
83
|
return ''
|
83
84
|
elsif length.nil? && @file_position.zero?
|
@@ -165,6 +166,9 @@ module Mongo
|
|
165
166
|
# @return [True]
|
166
167
|
def close
|
167
168
|
if @mode[0] == ?w
|
169
|
+
if @current_chunk['n'].zero? && @chunk_position.zero?
|
170
|
+
warn "Warning: Storing a file with zero length."
|
171
|
+
end
|
168
172
|
@upload_date = Time.now.utc
|
169
173
|
@files.insert(to_mongo_object)
|
170
174
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# --
|
2
|
+
# Copyright (C) 2008-2010 10gen Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
# ++
|
16
|
+
|
17
|
+
#:nodoc:
|
18
|
+
class Object
|
19
|
+
|
20
|
+
#:nodoc:
|
21
|
+
def returning(value)
|
22
|
+
yield value
|
23
|
+
value
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
#:nodoc:
|
29
|
+
class Hash
|
30
|
+
|
31
|
+
#:nodoc:
|
32
|
+
def assert_valid_keys(*valid_keys)
|
33
|
+
unknown_keys = keys - [valid_keys].flatten
|
34
|
+
raise(Mongo::MongoArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
data/lib/mongo/util/support.rb
CHANGED
@@ -14,13 +14,46 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
# ++
|
16
16
|
|
17
|
-
|
18
|
-
class Object
|
17
|
+
require 'digest/md5'
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
module Mongo
|
20
|
+
module Support
|
21
|
+
extend self
|
22
|
+
|
23
|
+
# Generate an MD5 for authentication.
|
24
|
+
#
|
25
|
+
# @param [String] username
|
26
|
+
# @param [String] password
|
27
|
+
# @param [String] nonce
|
28
|
+
#
|
29
|
+
# @return [String] a key for db authentication.
|
30
|
+
def auth_key(username, password, nonce)
|
31
|
+
Digest::MD5.hexdigest("#{nonce}#{username}#{hash_password(username, password)}")
|
32
|
+
end
|
33
|
+
|
34
|
+
# Return a hashed password for auth.
|
35
|
+
#
|
36
|
+
# @param [String] username
|
37
|
+
# @param [String] plaintext
|
38
|
+
#
|
39
|
+
# @return [String]
|
40
|
+
def hash_password(username, plaintext)
|
41
|
+
Digest::MD5.hexdigest("#{username}:mongo:#{plaintext}")
|
42
|
+
end
|
25
43
|
|
44
|
+
|
45
|
+
def validate_db_name(db_name)
|
46
|
+
unless [String, Symbol].include?(db_name.class)
|
47
|
+
raise TypeError, "db_name must be a string or symbol"
|
48
|
+
end
|
49
|
+
|
50
|
+
[" ", ".", "$", "/", "\\"].each do |invalid_char|
|
51
|
+
if db_name.include? invalid_char
|
52
|
+
raise InvalidName, "database names cannot contain the character '#{invalid_char}'"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
raise InvalidName, "database name cannot be the empty string" if db_name.empty?
|
56
|
+
db_name
|
57
|
+
end
|
58
|
+
end
|
26
59
|
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require 'mongo'
|
3
|
+
require 'test/unit'
|
4
|
+
require 'test/test_helper'
|
5
|
+
|
6
|
+
# Demonstrate features in MongoDB 1.4
|
7
|
+
class Features14Test < Test::Unit::TestCase
|
8
|
+
|
9
|
+
context "MongoDB 1.4" do
|
10
|
+
setup do
|
11
|
+
@con = Mongo::Connection.new
|
12
|
+
@db = @con['mongo-ruby-test']
|
13
|
+
@col = @db['new-features']
|
14
|
+
end
|
15
|
+
|
16
|
+
teardown do
|
17
|
+
@col.drop
|
18
|
+
end
|
19
|
+
|
20
|
+
context "new query operators: " do
|
21
|
+
|
22
|
+
context "$elemMatch: " do
|
23
|
+
setup do
|
24
|
+
@col.save({:user => 'bob', :updates => [{:date => Time.now.utc, :body => 'skiing', :n => 1},
|
25
|
+
{:date => Time.now.utc, :body => 'biking', :n => 2}]})
|
26
|
+
|
27
|
+
@col.save({:user => 'joe', :updates => [{:date => Time.now.utc, :body => 'skiing', :n => 2},
|
28
|
+
{:date => Time.now.utc, :body => 'biking', :n => 10}]})
|
29
|
+
end
|
30
|
+
|
31
|
+
should "match a document with a matching object element in an array" do
|
32
|
+
doc = @col.find_one({"updates" => {"$elemMatch" => {"body" => "skiing", "n" => 2}}})
|
33
|
+
assert_equal 'joe', doc['user']
|
34
|
+
end
|
35
|
+
|
36
|
+
should "$elemMatch with a conditional operator" do
|
37
|
+
doc1 = @col.find_one({"updates" => {"$elemMatch" => {"body" => "biking", "n" => {"$gt" => 5}}}})
|
38
|
+
assert_equal 'joe', doc1['user']
|
39
|
+
end
|
40
|
+
|
41
|
+
should "note the difference between $elemMatch and a traditional match" do
|
42
|
+
doc = @col.find({"updates.body" => "skiing", "updates.n" => 2}).to_a
|
43
|
+
assert_equal 2, doc.size
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context "$all with regexes" do
|
48
|
+
setup do
|
49
|
+
@col.save({:n => 1, :a => 'whale'})
|
50
|
+
@col.save({:n => 2, :a => 'snake'})
|
51
|
+
end
|
52
|
+
|
53
|
+
should "match multiple regexes" do
|
54
|
+
doc = @col.find({:a => {'$all' => [/ha/, /le/]}}).to_a
|
55
|
+
assert_equal 1, doc.size
|
56
|
+
assert_equal 1, doc.first['n']
|
57
|
+
end
|
58
|
+
|
59
|
+
should "not match if not every regex matches" do
|
60
|
+
doc = @col.find({:a => {'$all' => [/ha/, /sn/]}}).to_a
|
61
|
+
assert_equal 0, doc.size
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "the $not operator" do
|
66
|
+
setup do
|
67
|
+
@col.save({:a => ['x']})
|
68
|
+
@col.save({:a => ['x', 'y']})
|
69
|
+
@col.save({:a => ['x', 'y', 'z']})
|
70
|
+
end
|
71
|
+
|
72
|
+
should "negate a standard operator" do
|
73
|
+
results = @col.find({:a => {'$not' => {'$size' => 2}}}).to_a
|
74
|
+
assert_equal 2, results.size
|
75
|
+
results = results.map {|r| r['a']}
|
76
|
+
assert_equal ['x'], results.sort.first
|
77
|
+
assert_equal ['x', 'y', 'z'], results.sort.last
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "new update operators: " do
|
83
|
+
|
84
|
+
context "$addToSet (pushing a unique value)" do
|
85
|
+
setup do
|
86
|
+
@col.save({:username => 'bob', :interests => ['skiing', 'guitar']})
|
87
|
+
end
|
88
|
+
|
89
|
+
should "add an item to a set uniquely ($addToSet)" do
|
90
|
+
@col.update({:username => 'bob'}, {'$addToSet' => {'interests' => 'skiing'}})
|
91
|
+
@col.update({:username => 'bob'}, {'$addToSet' => {'interests' => 'kayaking'}})
|
92
|
+
document = @col.find_one({:username => 'bob'})
|
93
|
+
assert_equal ['guitar', 'kayaking', 'skiing'], document['interests'].sort
|
94
|
+
end
|
95
|
+
|
96
|
+
should "add an array of items uniquely ($addToSet with $each)" do
|
97
|
+
@col.update({:username => 'bob'}, {'$addToSet' => {'interests' => {'$each' => ['skiing', 'kayaking', 'biking']}}})
|
98
|
+
document = @col.find_one({:username => 'bob'})
|
99
|
+
assert_equal ['biking', 'guitar', 'kayaking', 'skiing'], document['interests'].sort
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "the positional operator ($)" do
|
104
|
+
setup do
|
105
|
+
@id1 = @col.insert({:text => 'hello',
|
106
|
+
:comments => [{'by' => 'bob',
|
107
|
+
'text' => 'lol!'},
|
108
|
+
{'by' => 'susie',
|
109
|
+
'text' => 'bye bye!'}]})
|
110
|
+
@id2 = @col.insert({:text => 'goodbye',
|
111
|
+
:comments => [{'by' => 'bob',
|
112
|
+
'text' => 'au revoir'},
|
113
|
+
{'by' => 'susie',
|
114
|
+
'text' => 'bye bye!'}]})
|
115
|
+
end
|
116
|
+
|
117
|
+
should "update a matching array item" do
|
118
|
+
@col.update({"_id" => @id1, "comments.by" => 'bob'}, {'$set' => {'comments.$.text' => 'lmao!'}}, :multi => true)
|
119
|
+
result = @col.find_one({"_id" => @id1})
|
120
|
+
assert_equal 'lmao!', result['comments'][0]['text']
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "Geoindexing" do
|
126
|
+
setup do
|
127
|
+
@places = @db['places']
|
128
|
+
@places.create_index([['loc', Mongo::GEO2D]])
|
129
|
+
|
130
|
+
@empire_state = ([40.748371, -73.985031])
|
131
|
+
@jfk = ([40.643711, -73.790009])
|
132
|
+
|
133
|
+
@places.insert({'name' => 'Empire State Building', 'loc' => ([40.748371, -73.985031])})
|
134
|
+
@places.insert({'name' => 'Flatiron Building', 'loc' => ([40.741581, -73.987549])})
|
135
|
+
@places.insert({'name' => 'Grand Central', 'loc' => ([40.751678, -73.976562])})
|
136
|
+
@places.insert({'name' => 'Columbia University', 'loc' => ([40.808922, -73.961617])})
|
137
|
+
@places.insert({'name' => 'NYSE', 'loc' => ([40.71455, -74.007124])})
|
138
|
+
@places.insert({'name' => 'JFK', 'loc' => ([40.643711, -73.790009])})
|
139
|
+
end
|
140
|
+
|
141
|
+
teardown do
|
142
|
+
@places.drop
|
143
|
+
end
|
144
|
+
|
145
|
+
should "find the nearest addresses" do
|
146
|
+
results = @places.find({'loc' => {'$near' => @empire_state}}).limit(2).to_a
|
147
|
+
assert_equal 2, results.size
|
148
|
+
assert_equal 'Empire State Building', results[0]['name']
|
149
|
+
assert_equal 'Flatiron Building', results[1]['name']
|
150
|
+
end
|
151
|
+
|
152
|
+
should "use geoNear command to return distances from a point" do
|
153
|
+
cmd = OrderedHash.new
|
154
|
+
cmd['geoNear'] = 'places'
|
155
|
+
cmd['near'] = @empire_state
|
156
|
+
cmd['num'] = 6
|
157
|
+
r = @db.command(cmd)
|
158
|
+
|
159
|
+
assert_equal 6, r['results'].length
|
160
|
+
r['results'].each do |result|
|
161
|
+
puts result.inspect
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|