mongo 0.19.1 → 0.19.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|