mongoid_geo 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -123,9 +123,9 @@ With the new @:geo@ option supplied by _mongoid-geo_ :
123
123
  Mongoid::Geo.spherical = true
124
124
  </pre>
125
125
 
126
- h2. News update (March 2)
126
+ h2. News update (May 9, 2011)
127
127
 
128
- * Added support for geoNear queries!!!
128
+ The geoNear queries can now convert the result into a Mongoid::Criteria, where distance from a given location is sorted in either descending or ascending (default) order
129
129
 
130
130
  <pre>
131
131
  class Address
@@ -145,18 +145,40 @@ class Position
145
145
  field :pos, :type => Array, :geo => true
146
146
  ...
147
147
  end
148
+ </pre>
149
+
150
+ Find all positions sorted nearest to the address loation
151
+ @nearest_positions = Position.geoNear(another_address.location, :pos)@
152
+
153
+ Perform distance locations in Speherical mode inside Mongo DB (default is :plane)
154
+ @nearest_positions = Position.geoNear(another_address.location, :pos, :mode => :sphere)@
155
+
156
+ Other options supported are: @:num, :maxDistance, :distanceMultiplier, :query@
157
+
158
+ GeoNear distance returns distance in degrees. Use distanceMultiplier to return in Miles or KM.
159
+
160
+ Set :distanceMultiplier to 6371 to get distance in KM
161
+ Set :distanceMultiplier to 3963.19 to get distance in Miles
162
+
163
+ You can also use the :unit option instead like this (supports :feet, :meters, :kms, :miles)
164
+
165
+ results = Address.geoNear @center.location, :location, :unit => :km
166
+
167
+ The query result is returned as an Array of Hashies
168
+
169
+ The result can be then converted to a Mongoid::Criteria if needed
170
+
171
+ pp results.as_criteria.to_a.map(&:distance)
172
+ pp results.as_criteria(:desc).to_a.map(&:distance)
173
+
174
+ Or converted to an array of Model instances
148
175
 
149
- # Find all positions sorted nearest to the address loation
150
- nearest_positions = Position.geoNear(another_address.location, :pos)
176
+ pp results.to_models.map(&:distance)
151
177
 
152
- # perform distance locations in Speherical mode inside Mongo DB (default is :plane)
153
- nearest_positions = Position.geoNear(another_address.location, :pos, :mode => :sphere)
178
+ Note that the :fromLocation field, stores the location the distance was last calculated as a hash of the Point it was calculated from
154
179
 
155
- # other options supported are: :num, :maxDistance, :distanceMultiplier, :query
180
+ @[23.5, -47].hash@
156
181
 
157
- # GeoNear distance returns distance in degrees. Use distanceMultiplier to return in Miles or KM.
158
- # set distanceMultiplier to 6371 to get distance in KM
159
- # set distanceMultiplier to 3963.19 to get distance in Miles
160
182
  </pre>
161
183
 
162
184
  If you need to operate on the Mongoid models referenced by the query result, simply call #to_models on it
@@ -26,6 +26,11 @@ module Mongoid #:nodoc
26
26
  end
27
27
 
28
28
  define_method("#{meth}=") do |value|
29
+ if options[:geo]
30
+ self.class.send :field, :distance, :type => Float
31
+ self.class.send :field, :fromLocation, :type => String
32
+ end
33
+
29
34
  if options[:type] == Array && options[:geo]
30
35
  value = case value
31
36
  when String
@@ -37,7 +42,7 @@ module Mongoid #:nodoc
37
42
  end
38
43
  value = value[0..1] if !value.nil?
39
44
  end
40
- value.reverse! if Mongoid::Geo.spherical && value
45
+ value.reverse! if Mongoid::Geo.spherical && value && !value.kind_of?(BSON::ObjectId)
41
46
  write_attribute(name, value)
42
47
  end
43
48
 
@@ -25,39 +25,38 @@ module Mongoid
25
25
  end
26
26
  end
27
27
 
28
- module Distance
29
- attr_reader :distance
30
-
31
- def set_distance dist
32
- @distance = dist
33
- end
34
- end
35
-
36
28
  module Model
37
29
  def to_model
38
30
  m = klass.where(:_id => _id).first.extend(Mongoid::Geo::Distance)
39
- m.set_distance distance
31
+ m.distance = distance
40
32
  m
41
33
  end
42
34
  end
43
35
 
44
36
  module Models
45
- def to_models
37
+ def to_models mode = nil
46
38
  distance_hash = Hash[ self.map {|item| [item._id, item.distance] } ]
39
+ from_hash = Hash[ self.map { |item| [item._id, item.fromLocation] } ]
47
40
 
48
41
  ret = to_criteria.to_a.map do |m|
49
- m.extend(Mongoid::Geo::Distance)
50
- m.set_distance distance_hash[m._id.to_s]
42
+ m.distance = distance_hash[m._id.to_s]
43
+ m.fromLocation = from_hash[m._id.to_s]
44
+ m.save if mode == :save
51
45
  m
52
46
  end
53
-
54
47
  ret.sort {|a,b| a.distance <=> b.distance}
55
48
  end
49
+
50
+ def as_criteria direction = :asc
51
+ to_models(:save)
52
+ ids = first.klass.where().map(&:_id)
53
+ Mongoid::Criteria.new(first.klass).where(:_id.in => ids, :fromLocation => first.fromLocation).send(direction, :distance)
54
+ end
56
55
 
57
56
  def to_criteria
58
- ids = map(&:_id)
59
- first.klass.where(:_id.in => ids)
60
- end
57
+ ids = map(&:_id)
58
+ Mongoid::Criteria.new(first.klass).where(:_id.in => ids).desc(:distance)
59
+ end
61
60
  end
62
61
 
63
62
  module Near
@@ -97,6 +96,7 @@ module Mongoid
97
96
  # Calculate distance in KM or Miles if mongodb < 1.7
98
97
  r[distance_meth] ||= calc_distance(r, center, location_attribute, options) if Mongoid::Geo.mongo_db_version < 1.7
99
98
  r['klass'] = klass
99
+ r['from'] = center.hash
100
100
  end
101
101
  query_result
102
102
  end
@@ -105,10 +105,11 @@ module Mongoid
105
105
  qres.map do |qr|
106
106
  res = Hashie::Mash.new(qr['obj'].to_hash).extend(Mongoid::Geo::Model)
107
107
  res.klass = qr['klass']
108
+ res.fromLocation = qr['from']
108
109
  res.distance = qr[distance_meth]
109
110
  res._id = qr['obj']['_id'].to_s
110
111
  res
111
- end
112
+ end
112
113
  end
113
114
 
114
115
  private
@@ -116,39 +117,8 @@ module Mongoid
116
117
  def distance_multiplier options
117
118
  distanceMultiplier = options[:distanceMultiplier]
118
119
  return distanceMultiplier if distanceMultiplier && Mongoid::Geo.mongo_db_version >= 1.7
119
-
120
- return radian_multiplier[options[:unit]] if options[:unit] && Mongoid::Geo.mongo_db_version >= 1.7
121
- unit_multiplier[options[:unit]] if options[:unit]
122
- end
123
-
124
- def unit_multiplier
125
- {
126
- :feet => 0.305,
127
- :ft => 0.305,
128
- :m => 1,
129
- :meters => 1,
130
- :meter => 1,
131
- :km => 6371,
132
- :kms => 6371,
133
- :mil => 3959,
134
- :mile => 3959,
135
- :miles => 3959
136
- }
137
- end
138
-
139
- def radian_multiplier
140
- {
141
- :feet => 364491.8,
142
- :ft => 364491.8,
143
- :m => 111170,
144
- :meter => 111170,
145
- :meters => 111170,
146
- :km => 111.17,
147
- :kms => 111.17,
148
- :mil => 69.407,
149
- :mile => 69.407,
150
- :miles => 69.407
151
- }
120
+ return Mongoid::Geo::Unit.distMultiplier(options[:unit]) if options[:unit]
121
+ 1
152
122
  end
153
123
 
154
124
  def query_results klass, query
@@ -0,0 +1,83 @@
1
+ module Mongoid
2
+ module Geo
3
+ class Unit
4
+ class << self
5
+ def key unit = :km
6
+ unit = unit.to_sym
7
+ methods.grep(/_unit/).each do |meth|
8
+ return meth.to_s.chomp('_unit').to_sym if send(meth).include? unit
9
+ end
10
+ raise ArgumentError, "Unknown unit key: #{unit}"
11
+ end
12
+
13
+ def distMultiplier unit = :km
14
+ unit_key = key(unit)
15
+ return radian_multiplier[unit_key] if unit_key && Mongoid::Geo.mongo_db_version >= 1.7
16
+ unit_multiplier[unit_key] if unit_key
17
+ end
18
+
19
+ def precision
20
+ {
21
+ :feet => 0,
22
+ :meters => 2,
23
+ :kms => 4,
24
+ :miles => 4,
25
+ :radians => 4
26
+ }
27
+ end
28
+
29
+ # from mongoid-geo, as suggested by niedhui :)
30
+ def radian_multiplier
31
+ {
32
+ :feet => 364491.8,
33
+ :meters => 111170,
34
+ :kms => 111.17,
35
+ :miles => 69.407,
36
+ :radians => 1
37
+ }
38
+ end
39
+
40
+ def unit_multiplier
41
+ {
42
+ :feet => 0.305,
43
+ :meters => 1,
44
+ :kms => 6371,
45
+ :miles => 3959
46
+ }
47
+ end
48
+
49
+ def meters_map
50
+ {
51
+ :feet => 3.2808,
52
+ :meters => 1,
53
+ :kms => 0.001,
54
+ :miles => 0.00062137,
55
+ :radians => 111170
56
+ }
57
+ end
58
+
59
+ protected
60
+
61
+ def feet_unit
62
+ [:ft, :feet, :foot]
63
+ end
64
+
65
+ def meters_unit
66
+ [:m, :meter, :meters]
67
+ end
68
+
69
+ def kms_unit
70
+ [:km, :kms, :kilometer, :kilometers]
71
+ end
72
+
73
+ def miles_unit
74
+ [:mil, :mile, :miles]
75
+ end
76
+
77
+ def radians_unit
78
+ [:rad, :radians]
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
data/lib/mongoid/geo.rb CHANGED
@@ -4,6 +4,7 @@ module Mongoid
4
4
  end
5
5
 
6
6
  require 'mongoid/geo/point'
7
+ require 'mongoid/geo/unit'
7
8
  require 'mongoid/geo/fields'
8
9
  require 'mongoid/geo/criteria'
9
10
  require 'mongoid/geo/index'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_geo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-05-04 00:00:00.000000000Z
12
+ date: 2011-05-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &2152917100 !ruby/object:Gem::Requirement
16
+ requirement: &2152937900 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '2.4'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2152917100
24
+ version_requirements: *2152937900
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: mongoid
27
- requirement: &2152916640 !ruby/object:Gem::Requirement
27
+ requirement: &2152965320 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 2.0.1
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *2152916640
35
+ version_requirements: *2152965320
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: bson
38
- requirement: &2152916180 !ruby/object:Gem::Requirement
38
+ requirement: &2152964860 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '1.3'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *2152916180
46
+ version_requirements: *2152964860
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: activesupport
49
- requirement: &2152915720 !ruby/object:Gem::Requirement
49
+ requirement: &2152964400 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 3.0.4
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *2152915720
57
+ version_requirements: *2152964400
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: hashie
60
- requirement: &2152931640 !ruby/object:Gem::Requirement
60
+ requirement: &2152963940 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: 0.4.0
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *2152931640
68
+ version_requirements: *2152963940
69
69
  description: Geo spatial extension on Mongoid 2, to add more geo-spatial capabilities
70
70
  email:
71
71
  - kmandrup@gmail.com
@@ -85,6 +85,7 @@ files:
85
85
  - lib/mongoid/geo/index.rb
86
86
  - lib/mongoid/geo/inflections.rb
87
87
  - lib/mongoid/geo/point.rb
88
+ - lib/mongoid/geo/unit.rb
88
89
  - lib/mongoid/geo.rb
89
90
  - lib/mongoid_geo.rb
90
91
  - MIT-LICENSE
@@ -110,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
111
  version: 1.3.6
111
112
  requirements: []
112
113
  rubyforge_project:
113
- rubygems_version: 1.7.2
114
+ rubygems_version: 1.8.0
114
115
  signing_key:
115
116
  specification_version: 3
116
117
  summary: Adds extra convenience methods for geo-spatial operations etc.